ایران سرفراز- نرم افزار وپروژهای دانشجویی


نرم افزار وپروژهای دانشجویی

فصل ششم وراثت و چند ریختی در #C

<!-- /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman";} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} -->

- فصل ششم

C# وراثت و چند ریختی در  

Mohsen_mahyar@yahoo.com

آنچه که در این فصل یاد خواهید گرفت:

مفاهیم ارثبری همچون تخصص و تعمیم

تشخیص و ایجاد سلسله مراتب ارثبری

دسترسی به سازندههای کلاس پایه

چندریختی و نحوه پیادهسازی آن

کردن متدها override • ایجاد نسخههای مختلف از یک متد به کمک

آشنایی با کلاسهای انتزاعی و مهر شده و پیادهسازی این کلاسها

در فصلهای قبلی نحوهی تعریف یک کلاس جدید و ارتباط ما بین کلاسها, انجمن, تخصص1 و تجمع را بررسی کردیم. این

پیادهسازی می شود. در این فصل نحوهی برخورد با کلاسهای #C فصل روی تخصص تمرکز دارد که از طریق وراثت در

تخصصی بصورت کلاسهای کلی پایه نیز شرح داده میشود که پروسهی چندریختی 2 نام دارد.

-1-6 تخصص و تعمیم 3

کلاسها و نمونههای آنها در خلاء وجود ندارند، بلکه در یک دنیا از رابطهها و دستهها زندگی میکنند. تخصص, یکی از

تشریح می شود. زمانی که میگوییم سگ is-a مهمترین رابطه های مابین اشیاء در دنیای واقعی است که بصورت یک رابطه

یک پستاندار است، بدین معنی است که سگ نوع خاصی از پستاندار است و آن همه مشخصه 4های یک پستاندار را دارد. اما

این مشخصه ها را به وسیله مشخصه های جنس سگ اختصاصی میکنند. گربه نیز یک پستاندار است، پس انتظار داریم بعضی

از ویژگیهای سگ را به اشتراک گذارند که درعموم پستانداران وجود دارند.

1 Specialization

2 Polumorphism

3 Generalization

4 characteristic

فصل ششم- وراثت و چندریختی

107

رابطههای اختصاصی کردن و تعمیم دادن, سلسله مراتبی و دوسویه هستند. اختصاصی کردن روی دیگر سکهی تعمیم است.

پستاندار, موارد مشترک مابین سگها و گربهها را تعمیم میدهد و سگها و گربهها, پستانداران را به انواع داده خاص خود

اختصاصی میکنند.

چون این رابطه ها یک درخت رابطه ای ایجاد می کنند، پس رابطه ها سلسله مراتبی هستند که انواع داده ها ی اختصاصی

از انواع تعمیم شده انشعااب شده اند. همان طور که از سلسله مراتب به سمت بالا حرکت می کنید، تعمیم بیشتر مشاهده می

کنید. همان طورکه از سلسله مراتب به سمت پایین حرکت می کنید، آن را اختصاصی می کنید. پس گربه, پستاندار را در

داشتن چنگ ها و خرخر کردن اختصاصی می کند.

پنجره هستند، نشان میدهید که ویژگیها و رفتارهایی از پنجره وجود Listbox,Button بطور مشابه زمانیکه میگویید

را تعمیم ListBox,Button دارند که انتظار دارید دراین دو نوع داده بیایند. بعبارت دیگر, پنجره, ویژگیهای مشترک

میکند، در حالی که هر کدام ویژگیها و رفتارهای مخصوص خود را اختصاصی میکنند.

چندین علامت بصری 1 دارد که کلاسها را با کادر UML . یک زبان استاندارد برای تشریح یک سیستم شیگراست ,UML

مستطیلی نمایش میدهند. نام کلاس در بالای کادر ظاهر میگردد و متدها و اعضا در داخل کادر نمایش داده میشوند. در

1 مدل کنید. به خط جهتدار از کلاس اختصاصی شده به کلاس تعمیم شده - روابط اختصاصیکردن را بصورت شکل 6 ,UML

اشاره میکنند. Window به کلاس کلی ListBox و Button توجه کنید. در شکل زیر, کلاسهای اختصاصی شدهی

1- روابط اختصاصی کردن - شکل 6

به اشتراک گذاشتن عملکرد دو کلاس، غیرمعمول است. چون میتوانید این مشترکات را در یک کلاس پایه قرار دهید که

نسبت به کلاسهای اختصاصی شده, کلی تر است. این عمل, استفاده مجدد کد مشترک را ممکن میسازد و نگهداری کد

سادهتر میشود، چون به جای اینکه تغییرات در هر کلاس جداگانه انجام شود در کلاس منفردی رخ میدهد.

RadioButton ,CheckBox , 2) را آغاز کردید. بعد از کار با - برای مثال: فرض کنید ایجاد یک دنباله از اشیاء (شکل 6

ها میفهمید که آنها ویژگیها و رفتارهای معینی را به اشتراک میگذارند که نسبت به پنجره اختصاصیتر CommandButton

تجزیه کنید و سلسله Button هستند و ممکن است این رفتار و ویژگیهای مشترک را به یک کلاس پایه مشترک بنام

3). این مثال نحوهی استفاده از تعمیم در توسعهی شیگرایی را نشان میدهد. - مراتب وراثت را مجدداً مرتب کنید(شکل 6

1 Visual

Mohsen_mahyar@yahoo.com - C# برنامه نویسی

108

2-ایجاد یک دنباله از اشیاء - شکل 6

3-رابطهی ما بین کلاسهای تجزیهشده - شکل 6

مشتق شده Button و ListBox 3 رابطهی مابین کلاسهای تجزیهشده را نشان میدهد و دو کلاس - شکل 6 UML دیاگرام

از RadioButton , اختصاصی میشود. در نهایت CheckBox و Command به Button را نمایش میدهد که Window از

مشتق میشود. CheckBox

این بهترین یا ضروریترین روش سازماندهی این اشیاء نیست، اما یک نقطهی شروع معقول برای فهم نحوهی ارتباط این نوع

دادهها با دیگری است.

-2-6 وراثت

رابطهی اختصاصی کردن با استفاده از یک قاعده بنام وراثت پیادهسازی میشود. این تنها راه پیادهسازی اختصاصی ,#c در

ارثبری , Window از ListBox کردن نیست، بلکه عمومیترین و طبیعیترین راه پیادهسازی این رابطه است. این گفته که

را اختصاصی میکند. window میکند, نشان میدهد که آن

ویژگیها و ListBox به عنوان یک کلاس مشتق شده اشاره میشود و ListBox یک کلاس پایه 1 بیان میشود و Window

را مشتق گرفته و نیازهای خاص خود را اختصاصی میکند. اغلب به کلاس پایه,کلاس پدر 2 گفته میشود و Window رفتار

ریشه گفته میشود. (object) کلاس مشتق شده, کلاس فرزند 3 خوانده میشود و بالاترین کلاس

1 Base class

2 Parent

3 Child

فصل ششم- وراثت و چندریختی

109

-1-2-6 پیادهسازی وراثت

یک کلاس مشتق شده را با اضافهکردن یک کالن بعد از نام کلاس که به دنبال آن نام کلاس پایه قرار میگیرد، ایجاد #c

میکند.

public class ListBox : Window

مشتق میشود. میتوان کالن را بصورت "مشتق می Window اعلان میکند که از ListBox این کد یک کلاس جدید بنام

شود از" خواند.

کلاس مشتق شده همهی اعضای کلاس پایه را به ارث میبرد و متدهای کلاس مشتق شده به همهی اعضای عمومی و حفاظت

شدهی کلاس پایه دسترسی دارند.کلاس مشتق شده در پیادهسازی نسخهی جدید خود از متد کلاس پایه آزاد است. این

انجام میشود. new عمل, پنهان کردن متد کلاس پایه نامیده میشود و از طریق علامتگذاری متد با کلمهی کلیدی

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

1 میبینید: - همان طور که در مثال 6

1- مثال 6

using System;

public class Window

{

// constructor takes two integers to

// fix location on the console

public Window( int top, int left )

{

this.top = top;

this.left = left;

}

// simulates drawing the window

public void DrawWindow( )

{

Console.WriteLine( "Drawing Window at {٠}, {١}",top, left );

}

// these members are private and thus invisible

// to derived class methods; we'll examine this

// later in the chapter

private int top;

private int left;

}

// ListBox derives from Window

public class ListBox : Window

{

// constructor adds a parameter

public ListBox( int top, int left, string theContents ) :

base( top, left ) // call base constructor

{

mListBoxContents = theContents;

}

// a new version (note keyword) because in the

// derived method we change the behavior

public new void DrawWindow( )

{

base.DrawWindow( ); // invoke the base method

Console.WriteLine( "Writing string to the listbox: {٠}",mListBoxContents );

}

private string mListBoxContents; // new member variable

}

public class Tester

{

public static void Main( )

#C برنامهنویسی

110

{

// create a base instance

Window w = new Window( ۵, ١٠ );

w.DrawWindow( );

// create a derived instance

ListBox lb = new ListBox( ٢٠, ٣٠, "Hello world" );

lb.DrawWindow( );

}

}

خروجی بصورت زیر است:

Drawing Window at ۵, ١٠

Drawing Window at ٢٠, ٣٠

Writing string to the listbox: Hello world

()DrawWindow شروع میشود. این کلاس یک سازنده و یک متد ساده به نام Window 1 با اعلان کلاس پایهی - مثال 6

وجود دارند. این برنامه در بخشهای بعدی بطور دقیق تحلیل میشود. left و top پیادهسازی میکند. دو فیلد خصوصی

-2-2-6 فراخوانی سازندههای کلاس پایه

مشتق میشود و سازندهی خود را دارد که سه پارامتر میگیرد. سازنده Window از ListBox 1 کلاس جدید - در مثال 6

سازندهی پدر خود را با قرار دادن کالن (:) بعد از لیست پارامترهای خود احضار میکند و سپس سازندهی کلاس ,ListBox

احضار میکند. base پایه ی خود را با کلمهی کلیدی

public ListBox( int theTop, int theLeft, string theContents):

base(theTop, theLeft) // call base constructor

چون کلاسها نمیتوانند سازنده را به ارث ببرند, یک کلاس مشتق شده باید سازندهی خود را پیادهسازی کند و فقط میتواند

سازندهی کلاس پایهی خود را بطور صریح فراخوانی کند. اگر کلاس پایه, یک سازندهی پیش فرض دارد، نیاز نیست سازندهی

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

میشود. با این وجود، اگرکلاس پایه, سازندهی پیشفرض نداشته باشد, هر سازندهی کلاس مشتق شده باید به طور صریح

کلاس پایه را برای شی جاری تعیین میکند. ,base یکی از سازندههای کلاس پایهی خود را احضار کند. کلمهی کلیدی

-3-2-6 کنترل دسترسی

و private و public میتوانید میدان دید یک کلاس و اعضای آن را از طریق کاربرد معرفهای دسترسی همچون

محدود کنید. protected

کلاسها همانند اعضای خود میتوانند با هر سطح دستیابی طرٌاحی شوند. اگر یک عضوکلاس معرف دسترسی مختلفی نسبت

را بصورت زیر تعریف کنید: MyClass به خود کلاس داشته باشد, حداقل دسترسی به آن اعمال میشود. پس اگر کلاس

public class MyClass

{

// ...

protected int myValue;

}

به هر کلاس public محافظت شده است. یک کلاس myValue باشد، قابلیت دستیابی به public حتی اگر خود کلاس

ایجاد کنید که از MyOtherClass دیگر که میخواهد با آن تعامل داشته باشد نمایان است. اگر یک کلاس دیگر بنام

مشتق میشود. MyClass

public class MyClass : MyOtherClass

{

Console.WriteLine("myInt: {٠}", myInt);

}

فصل ششم- وراثت و چندریختی

111

مشتق میشود و MyClass از MyOtherClass دسترسی داشته باشد، چون myInt میتواند به MyOtherClass کلاس

دسترسی داشته باشد. myInt مشتق نشده باشد، نمیتواند به MyClass هر کلاسی که از

توجه: ایجاد متدها و خصوصیات محافظت شده نسبت به ایجاد فیلدهای محافظت شده معمولتر است.

تقریبا فیلدها همواره خصوصی هستند.

-3-6 چند ریختی

را ایجاد کردید، ListBox دو جنبهی قدرتمند برای وراثت وجود دارد: یکی قابلیت استفادهی مجدد است. زمانی که کلاس

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

است. پس چندریختی به قابلیت استفاده از چندین شکل یک نوع داده بدون توجه به جزئیات آن اشاره دارد.

زمانی که شرکت مخابرات یک سیگنال زنگ به تلفن شما ارسال میکند، نوع تلفن شما در طرف دیگر خط را نمیشناسد.

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

هر نمونهی مشتق شده از این نوع داده نحوه زنگ خوردن خود را بداند. زمانی که شرکت مخابرات به تلفن شما سیگنال زنگ

ارسال میکند، فقط متد زنگ تلفن شما را فراخوانی میکند. در اصل با تلفن شما بصورت چندریختی رفتار میکند.

-1 ایجاد انواع دادهی چندریختی -3-6

است، شما انتظار دارید در هر جایی که میخواهید پنجره Window نیز یک Button است و Window یک ListBox چون

را بکار برید، قادر باشید یکی از این دو را بکار برید. برای مثال احتمال دارد یک فرم یک کلکسیون از همه نمونههای مشتق

شده از پنجره که تحت مدیریت خود است را نگه دارد. زمانی که پنجره باز میشود، آن میتواند از هر پنجره بخواهد که

خودش را رسم کند. برای این عمل، فرم لازم ندارد که نوع دادهی اصلی مشتق شده را بداند. خلاصه اینکه فرم میخواهد با

اشیاء پنجره بصورت چندریختی رفتار کند.

چندریختی را در دو مرحله پیادهسازی کنید:

-1 یک کلاس پایه با متدهای مجازی ایجاد کنید.

میکنند. override -2 کلاسهای مشتق شدهای ایجاد کنید، که رفتار متدهای مجازی کلاس پایه را

علامت گذاری کنید. برای virtual برای ایجاد یک متد در کلاس پایه که چندریختی را پشتیبانی کند، آن متد را بصورت

virtual 1 چندریخت است. کلمهی کلیدی - در کلاس پنجرهی مثال 6 ()Drawwindow مثال، جهت نشان دادن اینکه متد

را بصورت زیر به اعلان آن متد اضافه کنید.

public virtual void DrawWindow( )

کلاس پایه، بوسیله پیادهسازی نسخهی جدید خود ()DrawWindow هر کلاس مشتق شده برای ارثبری و کاربرد متد

کند. نسخهی override را ()DrawWindow آزاد است. اگر یک کلاس مشتق شده متد ()DrawWindow از

کننده برای هر نمونه از کلاس مشتق شده احضار خواهد شد. متد مجازی کلاس پایه را با استفاده از کلمهی override

کننده override کنید و سپس کد تغییر یافته را به متد override در تعریف متد کلاس مشتق شده override کلیدی

کردن متدهای مجازی را نشان میدهد. override 2 نحوهی - اضافه کنید. مثال 6

2- متدهای مجازی - مثال 6

using System;

public class Window

{

// constructor takes two integers to

Mohsen_mahyar@yahoo.com - C# برنامه نویسی

112

// fix location on the console

public Window( int top, int left )

{

this.top = top;

this.left = left;

}

// simulates drawing the window

public virtual void DrawWindow( )

{

Console.WriteLine( "Window: drawing Window at {٠}, {١}",top, left );

}

// these members are protected and thus visible

// to derived class methods. We'll examine this

// later in the chapter. (Typically, these would be private

// and wrapped in protected properties, but the current approach

// keeps the example simpler.)

protected int top;

protected int left;

} // end Window

// ListBox derives from Window

public class ListBox : Window

{

// constructor adds a parameter

// and calls the base constructor

public ListBox(int top,int left,string contents ) : base( top, left )

{

listBoxContents = contents;

}

// an overridden version (note keyword) because in the

// derived method we change the behavior

public override void DrawWindow( )

{

base.DrawWindow( ); // invoke the base method

Console.WriteLine( "Writing string to the listbox: {٠}",listBoxContents );

}

private string listBoxContents; // new member variable

} // end ListBox

public class Button : Window

{

public Button(

int top,

int left ) : base( top, left )

{}

// an overridden version (note keyword) because in the

// derived method we change the behavior

public override void DrawWindow( )

{

Console.WriteLine( "Drawing a button at {٠}, {١}\n",top, left );

}

} // end Button

public class Tester

{

static void Main( )

{

Window win = new Window( ١, ٢ );

ListBox lb = new ListBox( ٣, ۴, "Stand alone list box" );

Button b = new Button( ۵, ۶ );

win.DrawWindow( );

lb.DrawWindow( );

b.DrawWindow( );

Window[] winArray = new Window[٣];

winArray[٠] = new Window( ١, ٢ );

winArray[١] = new ListBox( ٣, ۴, "List box in array" );

winArray[٢] = new Button( ۵, ۶ );

for ( int i = ٠; i < ٣; i++ )

فصل ششم- وراثت و چندریختی

113

{

winArray[i].DrawWindow( );

} // end for

} // end Main

} // end Tester

خروجی بصورت زیر است:

Window: drawing Window at ١, ٢

Window: drawing Window at ٣, ۴

Writing string to the listbox: Stand alone list box

Drawing a button at ۵, ۶

Window: drawing Window at ١, ٢

Window: drawing Window at ٣, ۴

Writing string to the listbox: List box in array

Drawing a button at ۵, ۶

خود را پیادهسازی میکند. ()DrawWindow از پنجره مشتق میشود و نسخهی ListBox ،2- در مثال 6

public override void DrawWindow( )

{

base.DrawWindow( ); // invoke the base method

Console.WriteLine ("Writing string to the listbox: {٠}", listBoxContents);

}

کرده است. override را DrawWindow به کامپایلر میگوید این کلاس بطور عمدی نحوهی کار override کلمه ی کلیدی

خواهید کرد(کلاس override ، مشتق میشود Window را در کلاس دیگر که از ()DrawWindow بطور مشابه, متد

.(Button

را روی هر کدام ()DrawWindow ایجاد کرده و سپس Button و Window, ListBox در بدنهی مثال, سه شئ از انواع

فراخوانی کرده است.

Window win = new Window(١،٢);

ListBox lb = new ListBox(٣،۴,"Stand alone list box");

Button b = new Button(۵،۶);

win.DrawWindow( );

lb.DrawWindow( );

b.DrawWindow( );

به طور صحیح فراخوانی میشود. هنوز ()DrawWindow این کد همان طور که شما انتظار دارید کار میکند. برای هرکدام متد

ایجاد کنید. Window مفهوم واقعی چندریختی اعمال نشده است. سحر واقعی زمانی شروع میشود که یک آرایه از اشیاء

آزاد هستید. بطور مشابه Window در آرایهای از ListBox است، پس برای قرار دادن یک Window یک ListBox چون

را نیز به این آرایه اضافه کنید. Button میتوانید یک

Window[] winArray = new Window[٣];

winArray[٠] = new Window(١،٢);

winArray[١] = new ListBox(٣،۴,"List box in array");

winArray[٢] = new Button(۵،۶);

را Window تعریف میکند. سه خط بعدی اشیاء جدید Window برای نگهداشتن سه شی winArray خط اول یک آرایه بنام

به آرایه اضافه میکنند.

را روی هر کدام از این اشیاء فرا میخوانید، چه اتفاقی میافتد؟ ()DrawWindow زمانی که متد

for (int i = ٠; i < winArray.Length-١; i++)

{

winArray[i].DrawWindow();

}

را روی هر عنصر آرایه فراخوانی میکند. کامپایلر ()DrawWindow بکار میبرد. آن متد i این کد یک متغیر شمارنده بنام

را روی هرکدام از آنها فراخوانی کردهاید. ()DrawWindow دارد و شما متد Window میداند که آن سه شی

Mohsen_mahyar@yahoo.com - C# برنامه نویسی

114

Window علامتگذاری نکرده بودید، در هر بار اجرا، همان متد اصلی کلاس virtual را بصورت ()DrawWindow اگر متد

را به صورت مجازی علامتگذاری کردید و کلاس مشتق ()DrawWindow سه بار فراخوانی میشد. با این وجود, چون متد

را روی عناصر آرایه فراخوانی میکنید، همه چیز ()DrawWindow کرده است، زمانی که متد override شده آن متد را

مطابق انتظار شما پیش میرود. کامپایلر نوع دادهها را در زمان اجرای اشیاء واقعی تعیین میکند و متد صحیح هر کدام را

فراخوانی میکند و این ماهیت چندریختی است.

علامتگذاری می شوند. override کننده با کلمهی کلیدی override با توجه به اینکه, طبق این مثال, متدهای

( )public override void DrawWindow

شده را بکار برد. کامپایلر مسئول پیگیری override حال کامپایلر میداند که زمان برخورد با این اشیاء چند ریختی متد

اشاره میکند، ListBox نوع واقعی اشیاء و ادارهی دیر مقیدکردن 1 است. بنابراین زمانی که ارجاع پنجره واقعاً به یک شی

فراخوانی میشود. ()ListBox.DrawWindow متد

override و new -2 نسخهسازی 2 با -3-6

بصورت واضح انجام میدهد. این override کردن یک متد مجازی را با کلمهی کلیدی override ،C# برنامه نویس زبان

عمل در تولید نسخههای جدید از کد کمک میکند. تغییرات در کلاس پایه, کد موجود در کلاسهای مشتق شده را شکست

در جلوگیری از این مشکل کمک میکند. override نخواهد داد. نیاز به کلمهی کلیدی

توسط برنامهنویسان Button و ListBox 2 را نوشته است و کلاسهای - مثال 6 Window کلاس پایه A فرض کنید شرکت

,B را به عنوان کلاس پایه خریدهاند. برنا مهنویسان شرکت A شرکت Window نوشته شدهاند، که یک کپی از کلاس B شرکت

کمی کنترل دارند یا اصلاً ندارند. Window روی طراحی کلاس

اضافه کند. ListBox را به ()Sort تصمیم دارد، متد B حال فرض کنید, یکی از برنامهنویسان شرکت

public class ListBox : Window

{

public virtual void Sort( ) {...}

}

یک متد A را منتشر نکرده, مشکلی ندارد. برنامهنویس شرکت Window نسخهی دوم کلاس , A این کد تا زمانی که شرکت

خود اضافه میکند. Window به کلاس عمومی ()Sort

public class Window

{

// ...

public virtual void Sort( ) {...}

}

به عنوان یک متد مجازی پایه ، Window در کلاس ( )Sort متد مجازی جدید ،(++c در زبانهای شیگرای دیگر (همچون

قصد داشت. ListBox عمل میکند و این چیزی نیست که توسعهدهندهی ListBox در ()Sort برای متد

همواره بعنوان ریشهی گسیل 3 مجازی بررسی میگردد. virtual یک تابع ,#C از این پریشانی جلوگیری میکند. در #C

یک متد مجازی مییابد, به سلسله مراتبی وراثت قبلی نگاه نمیکند. اگر یک متد مجازی جدید #C بدین صورت, زمانی که

تغییر نمییابد. ListBox اضافه گردد، رفتار زمان اجرای Window به ()Sort

مجدداً کامپایل میشود, کامپایلر یک هشدار تولید میکند. ListBox زمانی که

1 Late binding

2 Versioning

3 Dispatch

فصل ششم- وراثت و چندریختی

115

...\class١.cs(۵۴،٢۴): warning CS٠١١۴: 'ListBox.Sort( )' hides

inherited member 'Window.Sort( )'.

To make the current member override that implementation,

add the override keyword. Otherwise add the new keyword.

توجه: هرگز از هشدارها صرف نظر نکنید , آنها را همانند خطاهایی در نظر گرفته و بررسی کنید.

new خود را با ListBox کلاس Sort برای حذفکردن هشدار, برنامهنویس باید قصد خود را معین کند. او میتواند متد

از متد مجازی پنجره نیست . override علامتگذاری کند تا نشان دهد آن یک

public class ListBox : Window

{

public new virtual void Sort( ) {...}

کند، فقط لازم override با این عمل، پیام هشدار را حذف میکنید. از طرف دیگر، اگر برنامهنویس میخواهد متد پنجره را

را بطور صریح بکار برد. override است که کلمهی کلیدی

public class ListBox : Window

{

public override void Sort( ) {...}

را به همهی متد های مجازی خود اضافه کنید. این یک new توجه : برای پرهیز از این هشدار ممکن است بخواهید کلمهی

در کد ظاهر میگردد, آن میخواهد نسخهسازی کد را مستندسازی کند. new ایدهی بدی است. زمانی که

به Window نه از ( )ListBox را از ()Sort مشتق کند, این کلاسهای مشتق شده، متد ListBox اگر برنامه نویس کلاسی از

ارث میبرند.

-4-6 کلاسهای انتزاعی 1

شکل و ظاهر متفاوتی دارد. لیستهای باز شو با دکمهها خیلی تفاوت دارند. بطور واضح هر زیرکلاسی از ,Window هر نوع

ما مجبور به این کار نیستیم. برای اینکه window خود را پیادهسازی کند. براساس کلاس ()DrawWindow باید متد Window

یک کلاس را به پیادهسازی یک متد از کلاس پایه مجبور کنیم, لازم است متد را بصورت انتزاعی طراحی کنیم.

یک متد مجازی, هیچ پیادهسازی ندارد. آن یک نام و نشانه 2 ایجاد میکند که باید در همهی کلاسهای مشتق شده

پیادهسازی شود. بعلاوه, ایجاد حداقل یک متد انتزاعی در هر کلاس, آن کلاس را انتزاعی میکند.

کلاسهای انتزاعی, یک پایه برای کلاسهای مشتق شده بنا مینهند. تعریف یک شی از کلاس انتزاعی نامعقول است. زمانی

را به ( )DrawWindow که متدی از یک کلاس را انتزاعی اعلان میکنید, ایجاد هر نمونه از آن کلاس را منع میکنید. اگر متد

Window نیز انتزاعی میشود. پس میتوانید از Window طرٌاحی کنید، پس کلاس Window عنوان یک متد انتزاعی در کلاس

مشتق بگیرید، ولی نمیتوانید نمونههایی از خود آن ایجاد کنید.

()DrawWindow باید متد Window انتزاعی بدین معنی است که هر کلاس مشتق شده از ()Window.DrawWindow ایجاد

منحصر به خود را پیادهسازی کند. اگر کلاس مشتق شده, متد انتزاعی را پیادهسازی نکند, کلاس مشتق شده نیز انتزاعی

خواهد شد و هیچ نمونهای از آن امکانپذیر نیست.

در ابتدای تعریف متد انجام میشود. abstract طراحی یک متد بعنوان انتزاعی با قرار دادن کلمهی کلیدی

abstract public void DrawWindow( );

1 Abstract

2 Signature

Mohsen_mahyar@yahoo.com - C# برنامه نویسی

116

(چون متد هیچ پیادهسازی ندارد، آکولادهای باز و بسته ندارد و فقط یک ; بعد از آن قرار دارد). اگر در تعریف یک کلاس

علامتگذاری شود . abstract یک یا چند متد انتزاعی باشد , تعریف کلاس باید

abstract public class Window

را ارائه میکند . ()DrawWindow انتزاعی و یک متد انتزاعی Window 3 ایجاد یک کلاس - مثال 6

3- مثال 6

using System;

public abstract class Window

{

// constructor takes two integers to

// fix location on the console

public Window( int top, int left )

{

this.top = top;

this.left = left;

}

// simulates drawing the window

// notice: no implementation

public abstract void DrawWindow( );

protected int top;

protected int left;

} // end class Window

// ListBox derives from Window

public class ListBox : Window

{

// constructor adds a parameter

public ListBox(int top,int left,string contents ) : base( top, left )

// call base constructor

{

listBoxContents = contents;

}

// an overridden version implementing the

// abstract method

public override void DrawWindow( )

{

Console.WriteLine( "Writing string to the listbox: {٠}",listBoxContents );

}

private string listBoxContents; // new member variable

} // end class ListBox

public class Button : Window

{

public Button(

int top,

int left ) : base( top, left ) { }

// implement the abstract method

public override void DrawWindow( )

{

Console.WriteLine( "Drawing a button at {٠}, {١}\n",top, left );

}

} // end class Button

public class Tester

{

static void Main( )

{

Window[] winArray = new Window[٣];

winArray[٠] = new ListBox( ١, ٢, "First List Box" );

winArray[١] = new ListBox( ٣, ۴, "Second List Box" );

winArray[٢] = new Button( ۵, ۶ );

for ( int i = ٠; i < ٣; i++ )

{

winArray[i].DrawWindow( );

فصل ششم- وراثت و چندریختی

117

} // end for loop

} // end main

} // end class Tester

خروجی بصورت زیر است:

Writing string to the listbox: First List Box

Writing string to the listbox: Second List Box

Drawing a button at ۵, ۶

بصورت انتزاعی اعلان شده است و نمیتوان نمونهای از آن تولید کرد.. اگر اولین عضو آرایه را Window 3, کلاس - در مثال 6

به جای دستور شماره 1 با دستور 2 جایگزین کنید:

winArray[0] = new ListBox(1،2,"First List Box"); 1

winArray[0] = new Window(1،2); 2

در زمان کامپایل خطای زیر تولید میگردد:

Cannot create an instance of the abstract class or interface 'Window'

میکنند. پس کلاسها override را میتوان نمونهسازی کرد، چون این کلاسها متد انتزاعی را Button و ListBox اشیاء

را واقعی (نه انتزاعی) میکنند.

علامتگذاری خواهند شد, تا virtual اغلب یک کلاس انتزاعی, متدهای غیرانتزاعی نیز دارد. بطور معمول این متدها نیز با

برنامهنویسانی که از کلاس انتزاعی مشتق میگیرند , آن کد پیادهسازی شده در کلاس انتزاعی را انتخاب کنند یا آنها را

override کنند. با این وجود، به منظور ایجاد یک نمونه از کلاس مشتق شده، باید همهی متد های انتزاعی override

شوند.

-5-6 کلاسهای مهرشده 1

طرف مفابل سکهی طراحی انتزاعی, طراحی مهرشده است. برخلاف یک کلاس انتزاعی که باید کلاسهایی از آن مشتق

قبل از اعلان کلاس قرار sealed شوند، یک کلاس مهرشده اجازه نمیدهد کلاسی از آن مشتق شود. کلمهی کلیدی

میگیرد تا مانع مشتق گرفتن شود. اغلب برای جلوگیری از وراثت تصادفی، کلاسها را بصورت مهرشده علامتگذاری

میکنند.

تغعیر یابد. کامپایل برنامه شکست میخورد. اگر سعی کنید این sealed به abstract از Window 3 اعلان - اگر در مثال 6

پروژه را بسازید ,کامپایلر خطای زیر را تولید میکند.

'ListBox' cannot inherit from sealed type 'Window'

زمانی که میدانید تولید کلاسهای مشتق شده از یک کلاس را نیاز نخواهیم داشت و زمانی که کلاس شما فقط خصوصیات و

را بکار ببرید. sealed متدهای ایستا دارد, مایکروسافت توصیه میکند

( Object) -6-6 ریشهی همه کلاسها

کلاس پایهی همهی کلاسهای دیگر است. یک Object . مشتق میشوند Object نهایتاً از کلاس ,#C همهی کلاسهای

کلاس پایه, پدر بلاواسطهی یک کلاس مشتق شده است. یک کلاس مشتق شده میتواند پایهی کلاسهای مشتق شدهی

کلاس ریشه است. C# , object دیگر باشد. کلاس ریشه، بالاترین کلاس یک درخت وراثت است. در

1 Sealed

#C برنامهنویسی

118

تعیین )()Equals کنند. به عنوان مثال، متدهای override چندین متد دارد. زیرکلاسها میتوانند آنها را Object کلاس

()Tostring یک رشته برای نمایش شی جاری بر میگرداند) را شامل است. متد ) ()ToString مساوی بودن دو شی) و متد

را خلاصه میکند. Object 1 متدهای - یک رشته با نام کلاسی که شی به آن تعلق دارد برمیگرداند. جدول 6

1- جدول 6

را برگرداند. Dog میکند تا وزن override را Object ارثبری شده از ()ToString متد Dog 4 کلاس - در مثال 6

4- مثال 6

using System;

public class Dog

{

private int weight;

// constructor

public Dog( int weight )

{

this.weight = weight;

}

// override Object.ToString

public override string ToString( )

{

return weight.ToString( );

}

}

public class Tester

{

static void Main( )

{

int i = ۵;

Console.WriteLine( "The value of i is: {٠}", i.ToString( ) );

Dog milo = new Dog( ۶٢ );

Console.WriteLine( "My dog Milo weighs {٠} pounds", milo);

}

}

Output:

The value of i is: ۵

My dog Milo weighs ۶٢ pounds

متد کار مربوطه

معادل بودن دو شی را ارزیابی میکند. ( )Equals

خود را برای استفاده در کلکسیونها hash اجازه میدهد اشیاء تابع GetHashCode( )

فراهم کنند.

دسترسی به نوعدادهی شی را فراهم میکند. ( )GetType

یک نمایش رشتهای ازنام نوع شی را فراهم میکند. ( )ToString

منابع خارج از حافظه را پاک میکند. بوسیلهی یک مخرب طراحی ( )Finalize

میشود.

فصل ششم- وراثت و چندریختی

119

را روی کلاس شما ()ToString رشتهها را به کار میبرند. این متدها, متد ( Console متدهای بعضی از کلاسها (همچون

به Dog نکرده باشید، کلمهی override را ()ToString فراخوانی خواهند کرد، اگر شما

نشانهی آن را فاش میکند: ()Object.ToString برگردانده میشود. مستندات متد Console.WriteLine

public virtual string ToString( );

است که هیچ پارامتری نمیگیرد و یک رشته بر میگرداند. همهی انواع دادهای درونی ( public آن یک متد مجازی

را احضار کنند. Object مشتق میشوند، میتوانند متدهای Object که از (int همچون

لازم نیست، چون وراثت از نوع ضمنی است. Object توجه :اعلان صریح مشتق شدن از

-7-6 خلاصه

توصیف میشود. عکس اختصاصی کردن, تعمیم است. is-a • اختصاصی کردن به عنوان رابطهی

اختصاصی کردن و تعمیم, متقابل و سلسله مراتبی هستند. اختصاصی کردن عمل متقابل تعمیم است. هرکلاس

میتواند چندین کلاس اختصاصی مشتق شده از آن داشته باشد. پس یک حالت انشعاب ایجاد میکند.

اختصاصی کردن را از طریق وراثت پیادهسازی میکند. #C •

کلاس پایه را به ارث میبرد و در اضافه کردن یا تغییر protected و public • کلاس مشتق شده ویژگیها و رفتار

دادن ویژگیها و رفتار خود آزاد هستند.

برای پیادهسازی وراثت نام کلاس پایه را بعد از یک کالن به دنبال نام کلاس مشتق شده بنویسید.

یک کلاس مشتق شده میتواند سازندهی کلاس پایه را با قرار دادن یک کالن بعد از لیست پارامترهای سازندهی

احضار کند. base خود با کلمهی کلیدی

را بکار ببرند. protected و public, private • کلاسها میتوانند شبیه اعضای خود معرفهای دسترسی

غلامتگذاری شده باشد، می تواند بوسیلهی کلاسهای مشتق شده virtual • متدی که در کلاس پایه به صورت

را در تعریف متد بکار برید، پیادهسازی override گردد. اگر کلاسهای مشتق شده کلمهی کلیدی override

شده override چندریختی انجام دادهاند. زمانی که متد مجازی را روی هر شی مشتق شده فراخوانی کنید، رفتار

احضار میشود.

هیچ پیادهسازی ندارد. آن فقط نام و نشانهی متد مجازی را فراهم میکند. این متد باید توسط abstract • یک متد

گردد. هر کلاسی که یک متذ انتزاعی دارد، خود نیز انتزاعی است و نمیتوان شیئی override کلاس مشتق شده

از آن ایجاد کرد.

مشتق گرفت. sealed • نمیتوان از کلاس

مشتق میشوند و تعدادی متد مفید را به ارث میبرند. Object نهایتا همهی کلاسها از #C • در

Mohsen_mahyar@yahoo.com - C# برنامه نویسی

 

   + MOHSEN GHASEMI - ۱۱:٢٠ ‎ب.ظ ; ۱۳۸٩/٤/٥