PDA

View Full Version : سوال: مشکل در ارث بری و شی گرایی



Rocker
جمعه 12 شهریور 1389, 23:46 عصر
سلام دوستان من به یک مشکل جدی بر خوردم که مربوط به مفاهیم شی گرایی است:

فرض کنید ما دو کلاس به نامهای MyList و MyItem داریم و در کلاس MyList یک متد داریم به نام GetName() که وظیفه اش برگرداندن محتوای ویژگی Name از کلاس MyList است یعنی MyList ابتدا از MyItem یک نمونه می گیرد و نام آنرا ObjItem می گزارد و سپس در متدش از آن استفاده میکند. کد زیر تعریف دو کلاس MyList و MyItem است :

public class MyList
{
private MyItem ObjItem = new MyItem();
public string GetItemName()
{
return ObjItem.GetName();
}
}


public class MyItem
{
private string name = "masoud";
public string GetName()
{
return name;
}

}

تا اینجای کار مشکلی وجود نداره یعنی با صدا زدن متد GetItemName از کلاس MyList رشته ی “masoud” رو برمیگردونه که مورد انتظار هم هست.

مشکل اصلی زمانی است که بخواهیم از این دو کلاس به عنوان سوپر کلاس استفاده کنیم و دو کلاس دیگر به نامهای PersonList و PersonItem بخواهند به ترتیب از کلاسهای MyList و MyItem ارث ببرند کدهای زیر تعریف دو کلاس PersonList و PersonItem می باشد :




public class PersonList : MyList
{
private PersonItem ObjItem = new PersonItem();
}

public class PersonItem : MyItem
{
private string name = "ali";
}




مشکل اصلی اینه که وقتی متد GetItemName رو از کلاس PersonList (که این متد رو از کلاس MyList به ارث برده) فراخوانی میکنیم عوض اینکه رشته ی “ali” رو برگردونه“masoud ” برمیگردونه.

در واقع کاری به کلاس PersonItem نداره.حتی با اضافه کردن این خط کد به کلاس PersonList هم کار درست نشد چون اولویت رو میزاره روی شی ObjectItemی که سوپرکلاس خودش به ارث برده است.

private PersonItem ObjItem = new PersonItem();


به نظرتون راه حلش چیه برای اینکه اون ObjItemی که در متد GetItemName (از کلاس MyList ) به کار رفته با یک شی از نوع PersonItem جایگزین شود ؟؟

ممنون از راهنماییتون

#aliyari_C
شنبه 13 شهریور 1389, 01:02 صبح
سلام
بهتر اگر می گفتی به خاطر چی می خوای همچین کاری کنی!


public class MyItem
{
protected string name = "masoud";

public virtual string GetName()
{
return name;
}

}



public class PersonItem : MyItem
{


public override string GetName()
{
return base.name = "ali";


}
}




این برداشت من از کاری که شما می خواین انجام بدین
اگر نامفهوم بود بگو
موفق و تندرست باشی
__________________________________________________ _________________________
چون به دریاه می توانی راه یافت.................سوی یک قطره چرا باید شتافت

C Sharp
شنبه 13 شهریور 1389, 08:27 صبح
public class MyItem
{
protected string name = "masoud";

public virtual string GetName()
{
return name;
}

}



public class PersonItem : MyItem
{


public override string GetName()
{
return base.name = "ali";


}
}

این برداشت من از کاری که شما می خواین انجام بدین

کاملا درسته ولی :
چرا base.name = ali ؟

this.name = ali یا name =ali کافی بود !

میتونه تو سازنده این عمل اختصاص صورت بگیره

Rocker
شنبه 13 شهریور 1389, 23:40 عصر
کاملا درسته ولی :
چرا base.name = ali ؟

this.name = ali یا name =ali کافی بود !

میتونه تو سازنده این عمل اختصاص صورت بگیره


سلام
بهتر اگر می گفتی به خاطر چی می خوای همچین کاری کنی!


public class MyItem
{
protected string name = "masoud";

public virtual string GetName()
{
return name;
}

}



public class PersonItem : MyItem
{


public override string GetName()
{
return base.name = "ali";


}
}



این برداشت من از کاری که شما می خواین انجام بدین
اگر نامفهوم بود بگو
موفق و تندرست باشی
__________________________________________________ _________________________
چون به دریاه می توانی راه یافت.................سوی یک قطره چرا باید شتافت

ممنون دوست عزیز من میخوام دو سوپر کلاس ایجاد کنم که یکیش به مفهومی مثله لیست رو داشته باشه (MyList) و دیگری مفهوم آیتمهای این لیست رو داشته باشه (MyItem) و بتونم از این کلاس ارث ببرم اما مشکل وقتیه که کلاس MyList داخل متدهاش باید از کلاس MyItem نمونه بگیره و از یک سری از متدهای MyItem استفاده کنه این باعث میشه که اگه از این دو سوپر کلاس ارث بری بشه کلاس ارث برده شده از MyList بازهم متدهای سوپر کلاس MyItem رو فراخوانی میکنه و نه کلاس ارث برده شده از MyItem.

به عبارت دیگه چطور میتونم دو سوپر کلاس ایجاد کنم تو یکی از یکی دیگه نمونه گرفته میشه و از متدهاش استفاده می شه و وقتی که از این دو سوپر کلاس ارث بری شد کلاسهای فرزند کارشون رو همونطور که انتظار داریم انجام بده.

امیدوارم که تونستم منظورم رو برسونم.

میلاد قاضی پور
یک شنبه 14 شهریور 1389, 00:01 صبح
دوست عزیز نباید هم مسعود رو بازگردونه . در واقع من اگه این اتفاق نمی افتاد متعجب میشدم .
کلاس پرسن لیست از مای لیست به ارث برده . مای لیست کلاسی هست که تابعی داره که اون تابع مقدار مسعود رو از یک کلاس دیگه میگیره و برگشت میده . در واقع اینا ربطی به کلاس پرسن آیتم ندارند اصلا. هیچ ارتباطی برقرار نشده .

#aliyari_C
یک شنبه 14 شهریور 1389, 00:22 صبح
من همون کاری رو که خواستی انجام دادم ,من اشتباه کردم که اشکالت رو نگفتم: برداشت شما طبق پیاده سازی کلاستون از شی گرا اشتباه است.
تعاریف شی گرا رو باید درک کن ,تا بر اسای اون پیاده سازی رو انجام بدی.(برای این کار مثال یک انسان رو پیاده سازی کن یعنی تبدیلش کن به شی گرا, من از همین طریق تونستم مفهوم رو بگیرم)

Rocker
یک شنبه 14 شهریور 1389, 02:12 صبح
من همون کاری رو که خواستی انجام دادم ,من اشتباه کردم که اشکالت رو نگفتم: برداشت شما طبق پیاده سازی کلاستون از شی گرا اشتباه است.
تعاریف شی گرا رو باید درک کن ,تا بر اسای اون پیاده سازی رو انجام بدی.(برای این کار مثال یک انسان رو پیاده سازی کن یعنی تبدیلش کن به شی گرا, من از همین طریق تونستم مفهوم رو بگیرم)

نه من با مفاهیم شی گرایی مشکلی ندارم تو دیزایگن پرتنها هم ندیدم که چطور میشه یک چنین چیزی رو پیاد کرد خوده بنده هم واقف هستم که این شکل از طراحی کلاس مشکل دارد.
و دقیقا هم میدونم کجای کار اشکال داره و مثال زدم تا بدونم کسی میدونه چطور میشه یه همچین چیزی رو به صورت ابسترکت پیاده سازی کرد.
مطمئنم باید یه راهی باشه . . .
به هر حال از توجهتون ممنونم
--------------------

دوست عزیز نباید هم مسعود رو بازگردونه . در واقع من اگه این اتفاق نمی افتاد متعجب میشدم .
کلاس پرسن لیست از مای لیست به ارث برده . مای لیست کلاسی هست که تابعی داره که اون تابع مقدار مسعود رو از یک کلاس دیگه میگیره و برگشت میده . در واقع اینا ربطی به کلاس پرسن آیتم ندارند اصلا. هیچ ارتباطی برقرار نشده .
بله خدمت دوستمون هم عرض کردم درسته نباید هم برگردونه اون مثالی که من زدم برای این بود که دوستان متوجه بشن که چه خواسته ای دارم.
و چطور میشه یک چنین چیزی رو پیاده سازی کرد
البته به صورت ابسترکت

اَرژنگ
یک شنبه 14 شهریور 1389, 03:16 صبح
و دقیقا هم میدونم کجای کار اشکال داره و مثال زدم تا بدونم کسی میدونه چطور میشه یه همچین چیزی رو به صورت ابسترکت پیاده سازی کرد.
مطمئنم باید یه راهی باشه . . .

البته به صورت ابسترکت

ببخشید ولی من منظورتان از اینکه "به شکل ابسترکت پیاده بشه" را نمیفهمم.
ابسترکت یعنی پیاده نسازی، یعنی اینکه به جایه اینکه کدی وجود داشته باشد، کد وجود نداشته باشد و به جاش جایه خالی که چگونه کدی میتونه پرش کند وجود داشته باشد.
توضیح دادید که چطور چیزی میخواهید ساخته بشه، ولی اینکه بعد از ساخته شدن به چکاری میاد را نگفتید.
تا جایی که دیدم چیزی که میخواهید ساخته بشد و روشهایی که برایه ساختنش استفاده میکنید (ارث بری) با هم دیگر تناقض دارند. ولی تناقض داشتن دلیل بر نشدن اینکار نمیشه، حالا حتماً چرا باید از ارث بری استفاده بشه؟ فرض کنید کد نهایی ساخته شده و در جایی که بایِد استفاده بشه ما چی میبینیم و چرا بکار میاد؟

Rocker
یک شنبه 14 شهریور 1389, 17:31 عصر
ببخشید ولی من منظورتان از اینکه "به شکل ابسترکت پیاده بشه" را نمیفهمم.
ابسترکت یعنی پیاده نسازی، یعنی اینکه به جایه اینکه کدی وجود داشته باشد، کد وجود نداشته باشد و به جاش جایه خالی که چگونه کدی میتونه پرش کند وجود داشته باشد.
توضیح دادید که چطور چیزی میخواهید ساخته بشه، ولی اینکه بعد از ساخته شدن به چکاری میاد را نگفتید.
تا جایی که دیدم چیزی که میخواهید ساخته بشد و روشهایی که برایه ساختنش استفاده میکنید (ارث بری) با هم دیگر تناقض دارند. ولی تناقض داشتن دلیل بر نشدن اینکار نمیشه، حالا حتماً چرا باید از ارث بری استفاده بشه؟ فرض کنید کد نهایی ساخته شده و در جایی که بایِد استفاده بشه ما چی میبینیم و چرا بکار میاد؟

دوست عزيز ابستركت پياده سازي ميشه اما نمونه گرفته نميشه.
خب آخر سر شما دو تا كلاس داري كه يكيش مثله يك ليست و ديگري مثله آيتمهاي ليسته.
و شما رو از شر نوشتن متدهاي تكراري راحت ميكنه و ديگر مزايايي كه ارث بري به ارمغان ميارء

اَرژنگ
یک شنبه 14 شهریور 1389, 17:52 عصر
دوست عزيز ابستركت پياده سازي ميشه اما نمونه گرفته نميشه.
معنی این جمله را من درک نمیکنم، در چه حالتی ابسترکت چنین معنی میتونه داشته باشد؟


خب آخر سر شما دو تا كلاس داري كه يكيش مثله يك ليست و ديگري مثله آيتمهاي ليسته.
اگر دو تا کلاس با خصوصیات مختلف لازم دارید چرا از یک کلاس ارث بری میکنند؟


و شما رو از شر نوشتن متدهاي تكراري راحت ميكنه و ديگر مزايايي كه ارث بري به ارمغان ميارء

ارث بری مفتی نیست، هر چیزی معایبی و مزایتی دارد.
اگر دنبال روشی میگردید که با ۲ روش مختلف با یک ابجکت برخورد کنید به اینترفیسها نگاه بندازید.
یا اینکه یک جایه طراحی اشتباه است یا اینکه مفهومات شیگرایی را به اشتباه پیاده میکنید و یا اینکه چیزی که در نظرتان است را ما هنوز نتونستیم درک کنیم.
اصلاً روش پیاده سازی و معنی ابسترکت را فراموش کنید، فرض کنید که همه چی درست پیاده شده، جایی که از کد این ۲ کلاس قراره استفاده بشه ما چی میبینیم؟ یعنی اینکه فرض کنید که فقط نحوه استفاده از این ۲ کلاس به چه شکلی است؟ فقط جایی که ازشان استفاده میشه را کدی که شبیه به کدی باشد که میخواهید ازش استفاده کنید را بنویسید.
چرا کاری را که میخواهید نمیشه با اینترفیس انجام داد؟

saeedalg
دوشنبه 15 شهریور 1389, 08:51 صبح
خوب چه انتظاری داری وقتی که اون متد مثلا GetName رو تو کلاس تعریف نکردی از اون استفاده کنی؟ میره تو کلاس پدر پیداش میکنه، برای اینکه این کار رو بکنی باید تو کلاس پدر متد GetName رو virtual تعریف کنی تو بچه هم override کنیش، اینجا از زدن کد تکراریو ... نمیتونی جلوگیری کنی چون اصلا کد تکراری نداری، هر کلاسی داره یه رفتاری ارایه میده مستقل، حالا فرض کن بتونی اون نام رو Dynamic تخصیص بدی اونوقت نیازی به کلاس بچه نیست، کار دیگه ای هم که میتونی بکنی اینه که تو Constructor بچه بنویسی base.Name = "cccc" و برای خود بچه هم دیگه نام آیتم نذاری.
کد تکراری وقتی نمیزنی که تو یه کامپوننت دیگه بخوای از یه همچین خصوصیتی استفاده کنده، یا وقتی که متدایی که واسه پدر Virtual تعریف کردی واسه بچه نیازی به override اون نداشته باشی.
در ضمن اگه میخوای OO بنویسی اون فیلدای private که بچه میتونه ببینه رو protected کن.