به نام خدا فصل هفتم وراثت
فهرست مطالب 1- انواع داده جدید 2- انواع داده انتزاعی 3- تعریف نوع 4- ادا و پکیج 5- بسته بندی مستقیم و غیرمستقیم 6- انواع پارامتردار 7- انواع داده انتزاعی کلی و نمونه سازی 8- وراثت 9 – چندریختی
طراحی و پیاده سازی انواع داده جدید 1- تعریف شی داده 1- مشخص کردن صفات نوع داده یا اطلاعاتی که باید دراین شی داده ذخیره شود.(صفات هر شی داده مثل نوع داده و نام معمولا در طول عمر آن عوض نمی شود) 2- تعیین عناصری که شی داده حاوی آن است. 2- تعریف عملیات که بر روی شی داده کارمی کنند. تمام فعالیت های طراحی را می توان به عنوان طراحی مشخصات نوع داده ی انتزاعی درنظرگرفت.(یعنی طراحی صفات و عملیات مورد نیاز)
طراحی و پیاده سازی انواع داده جدید 1- نمایش خاصی برای اشیاء داده با استفاده از انواع داده ای که در زبان موجود است یا سایر انواع داده انتزاعی. 2- پیاده سازی عملیات بر روی این اشیاء داده به صورت زیربرنامه هایی که آرگومان های آنها این اشیاء داده هستند.
مثال: برای نوشتن برنامه ثبت نام و تنظیم کلاس دانشگاه تعریف شی داده : Section صفات این شی داده : نام استاد ، شماره اتاق ، ظرفیت و... عناصر این شی داده : لیستی از دانشجویان ثبت نام شده تعریف عملیاتی که بر روی این شی داده کار می کنند: ایجاد Section جدید ، انتساب دانشجو به یک Section ، از بین بردن یک Sectionو ...
مثال: برای نوشتن برنامه ثبت نام و تنظیم کلاس دانشگاه پیاده سازی نوع داده Section : نمایش نام استاد به صورت یک رشته 10 کاراکتری ، نمایش لیست دانشجویان به صورت یک آرایه خطی و... پیاده سازی عملیات روی Section : زیربرنامه هایی که آرگومان های آنها ، این این شی داده باشد. نتیجه : برنامه نویس می تواند دقیقا مثل نوع صحیح و یا سایر انواع اولیه ، از نوع Section (نوع داده جدید)بدون توجه به جزئیات پیاده سازی آن ، از آن استفاده کند.
انواع داده انتزاعی نوع داده ی انتزاعی : نوع داده ی جدیدی است که توسط برنامه نویس تعریف می شود وشامل موارد زیراست: 1- نوع داده ای که توسط برنامه نویس تعریف می شود. 2- مجموعه ای از عملیات انتزاعی بر روی اشیایی ازآن نوع 3- بسته بندی اشیاء آن نوع ، به طوری که کاربر آن نوع نمی تواند آن اشیاء را بدون استفاده از این عملیات دستکاری کند. کل تعریف باید طوری بسته بندی شود که کاربر فقط با دانستن نام نوع و معنای عملیات آن ، بتواند آن را به کار گیرد.
انواع داده انتزاعی... مثلا : نمایش حافظه مربوط به مقادیرحقیقی و صحیح ، کاملا بسته بندی شده است، یعنی از برنامه نویس پنهان است .برنامه نویس بدون اینکه از جزئیات نمایش حافظه این انواع اطلاع داشته باشد ، از اشیای داده ی آنها استفاده می کند. فقط نام و عملیاتی را برای دستکاری آن نوع فراهم می بیند.
تعریف نوع: مکانیزمی برای توصیف دسته ای از اشیاء داده مکانیزمی برای توصیف دسته ای از اشیاء داده درتعریف نوع نام نوع تعریف می شود و اعلانی وجود دارد که ساختار دسته ای از اشیای کلاس را توصیف می کند. بدین ترتیب نام نوع به عنوان نام دسته ای از اشیاء داده محسوب می شود . هر وقت به اشیاء داده ای از آن ساختار نیاز باشد ، به جای تکرار توصیف ساختمان داده ، کافی است نام نوع ارائه شود. توجه : تعریف نوع ، نوع داده ی انتزاعی کامل را تعریف نمی کند ، زیرا عملیاتی را بر روی داده های آن نوع تعریف نمی کند.
به عنوان مثال: به رکوردهای A ،B و C نیاز باشد ، به طوری که ساختار آنها یکسان باشد. تعریف نوع زیر را در نظر بگیرد: Type Rational = record numerator: integer; denominator: integer: end اکنون اعلان زیر را در نظر بگیرید که A ، B و C را از نوع Retional درنظر می گیرد: var A, B ,c: Retional; تعریف ساختار شی داده ی نوع Retional ، به جای اینکه سه بار برای A ، B و C تکرار شود ، فقط یک بار ارائه می شود.
امّا : اما ساختار داخلی اشیاء داده نوع ، بسته بندی شده نیست. هر زیربرنامه ای که می تواند متغیری را از نوع جدید اعلان کند ، اجازه دارد به هر عنصر از نمایش آن نوع دستیابی داشته باشد. چنین زیر برنامه ای می تواند انواع تعریف شده بر روی آن اشیای داده را نادیده بگیرد و آنها را مستقیما دستکاری کند(به آنها دستیابی داشته باشد). مفهوم بسته بندی نوع داده انتزاعی ، این دستیابی را غیر ممکن می سازد، به طوری که ، فقط زیربرنامه هایی که به عنوان بخشی از خود نوع هستند می دانند اشیای داده آن نوع چگونه نمایش داده می شوند.
پس در ادامه... مکانیزمهایی را برای بسته بندی خودکار داده ها توصیف می کنیم (مانند پکیج در ادا) پکیج در ادا این مفهوم را طوری بسط می دهیم که عملیات بر روی این اشیا داده از طریق وراثت قابل استفاده باشند. مشخصات پکیج پیاده سازی پکیج
باید توجه کنیم که : مشخصات پکیج SectionType ، تمام داده ها ، انواع و زیربرنامه ها را تعریف می کند که توسط رویه هایی که در پکیج های دیگری اعلان شده اند، قابل مشاهده اند. اعلان is private برای Section نشان می دهد که ساختار داخلی اشیاء داده Section نباید توسط زیربرنامه هایی که از پکیچ استفاده می کنند قابل دستیابی باشد. جزئیات واقعی نوع Section ، در انتهای پکیج دربخش private آمده است.
مشخصات پکیج SectionType Package SectionType is type StudentID is integer; type Section(MaxSize : integer) is private; procedure AssignStudent(Sect: in out section; Stud in StudentID); procedure CreateSection(Sect: in out section; Instr in integer; Room in integer) ; private type Section(MaxSize : integer) is record Room: integer; instructor: integer; ClassSize: integer range 0 .. MaxSize := 0; Classroll: array (1 .. MaxSize) of StudentID; end record; end;
مثال: رویه های AssignStudent و createSection می توانند به آرایه ClassRoll دستیابی داشته باشند که عضوی از Section است، اما هر رویه دیگری که در خارج از پکیج قرار دارد نمی توانند به این آرایه دسترسی داشته باشد.حتی اگر متغیری از نوع Section را تعریف کرده باشند.
توجه داشته باشیم که: در بخش package body پیاده سازی رویه های اعلان شده در بخش مشخصات پکیج ، قرار دارد. بخش package body می تواند اشیاء داده و انواعی داشته باشد که توسط پکیچ های دیگر قابل مشاهده نباشد. مثلا : رویه ScheduleRoom فقط می تواند در AssignStudent و createSection فراخوانی شود. این نام درخارج از این پکیج ناشناخته است. 16
پیاده سازی پکیج SectionType Package body SectionType is procedure AssignStudent(…) is - statements to insert student on ClassRoll end; procedure CreateSection(…) is - Statements to initialize components of record procedure ScheduleRoom(…) is - Statements to schedule section in a room
خوب حالا یه سؤال ؟؟؟ به نظر شما چرا از بخش private در تعریف پکیج بالا استفاده شد تا اطلاعات موجود در آن فقط توسط بدنه پکیج مورد استفاده قرار گیرد؟ آیا نمی شد جزئیات نمایش در پکیج دیگری باشد و دراین پکیج اشاره گری به آن قرار داده می شد؟ چه مشکلی پیش می آمد؟ برای جواب به این سوال دو مدل را برای پیاده سازی اشیاء داده ی بسته بندی شده معرفی می کنیم: 1- بسته بندی غیرمستقیم 2- بسته بندی مستقیم
بسته بندی غیرمستقیم دراین حالت ، ساختار نوع داده انتزاعی به وسیله مشخصات پکیج A تعریف شده است. حافظه ی واقعی برای شی P در رکورد فعالیت پکیج A نگهداری می شود. در پکیج B ، که شی P را تعریف و استفاده می کند ، رکورد فعالیت باید اشاره گری به حافظه داده ی واقعی داشته باشد. در این حالت پیاده سازی نوع داده ی انتزاعی ، کاملا مستقل از کاربردش است. اگر ساختار P تغییر کند ، فقط لازم است پکیج A تغییر نماید. پکیج B باید بداند که شی P یک اشاره گر است و لازم نیست از فرمت داده ای که P به آن اشاره می کند باخبر باشد. رکورد فعالیت پکیج A رکورد فعالیت پکیج B P
معایب بسته بندی غیرمستقیم دستیابی به P تاوان اجرایی دارد. هر دستیابی به P مستلزم دستیابی غیرمستقیم به اشاره گر است تا حافظه واقعی پیدا شود. استفاده مکرر از P ممکن است گران تمام شود.
بسته بندی مستقیم: همانند حالت غیر مستقیم ، ساختار شی داده ی انتزاعی توسط مشخصات پکیج A تعریف شده است. دراین حالت ، حافظه واقعی P در رکورد فعالیت پکیج B نگهداری می شود. در این حالت ، شی داده ی P در رکورد فعالیت پکیج B ذخیره می شود. دستیابی به اجزای P ممکن است سریعتر انجام شود ، زیرا در رکورد فعالیت محلی ، می توان از مکانیزم آدرس پایه و آفست استفاده کرد و نیاز به دستیابی غیر مستقیم از طریق اشاره گر نیست. رکورد فعالیت پکیج B رکورد فعالیت پکیج A
ویژگی بسته بندی مستقیم: اگر نمایش شی انتزاعی عوض شود ، تمام نمونه های آن (مثلا پکیچ B) نیز باید دوباره کامپایل شوند. این کار ، تغییرات در سیستم را در زمان کامپایل کردن ، گران می کند ، اما کارایی اجرای آن بالاست.
پس : ادا از مدل بسته بندی مستقیم استفاده می کند تا کارایی اجرا را افزایش دهد. پس استفاده از شی داده انتزاعی مستلزم جزئیات نمایش شی است. بنابراین ، نیاز به بخش Private در مشخصات پکیج است.
تعریف انواعی که پارامتر دارند: وقتی نیاز به تعریف انواع مشابهی باشد ، زبان ممکن است پارامتری کردن تعریف نوع را تدارک ببیند.در این حالت شکلهای گوناگونی از پارامترها استفاده می شوند. مثال : تعریف نوع پارامتری برای Section اجازه می دهد که تعریف نوع دارای پارامتر MaxSize باشد که حداکثر ظرفیت کلاس را تعیین می کند : Type Section(MaxSize: integer) is record Room: integer; Instructor: integer: ClassSize: integer range 0 .. MaxSize; ClassRoll:array(1 .. MaxSize) of Student_ID; end record; اعلان متغیرهای زیر را درنظربگیرید: X: Section(100) -gives maximum size 100 Y: Section(25) -gives maximum size 25
انواع داده انتزاعی کلی این ساختار مثل تعریف نوع پارامتردار است که این پارامترها ممکن است تعریف عملیات و تعاریف نوع را در تعریف نوع انتزاعی تحت تأثیر قرار دهد. پارامترها می توانند علاوه بر مقادیر، نام نوع نیز باشند.
انواع داده انتزاعی کلی... مثال: پکیج ادا که در زیر آمده ، تعریف نوع کلی را برای نوع پشته کلی نشان می دهد که در آن ، نوع داده ای که در پشته ذخیره می شود و حداکثر طول پشته ، به عنوان پارامتر تعریف شده اند: Generic type Elem is private; Package AnyStackType is type Stack(Size:Psitive) is private; procedure Push(I: in Elem; S: in out Stack); procedure Pop(I: out Elem; S: in out Stack); Private type Stack(Size: Positive) is record StkStorage: array(1 .. Size) of Elem; Top: integer range 0 … Size := 0; end record; end AnyStackType;
نمونه سازی از نوع انتزاعی کلی تعریف پکیج کلی ، قالبی (template) را نشان می دهد که می تواند برای ایجاد انواع داده انتزاعی خاص مورد استفاده قرار گیرد. فرایند ایجاد نوع خاص از روی الگوی تعریف کلی ، نمونه سازی(instantiation) نام دارد. مثال: تعریف نوع پشته کلی ادا می تواند طوری نمونه سازی شود که تعریفی از نوع intstack تولید کند: Package IntstackType is new AnyStackType(elem => integer); در نتیجه ، پشته های نوع صحیح با طول متفاوت را نیز می توان اعلان کرد: Stk1: IntStackType.Stack(100); NewStk: IntStackType.Stack(25);
پیاده سازی نوع داده انتزاعی کلی: پیاده سازی ساده ای دارد. پارامترهای پکیج کلی وقتی که تعریف پکیج نمونه سازی می شود ، به آن ارسال می گردد. کامپایلر از تعریف پکیج کلی به عنوان یک قالب استفاده می کند، مقادیر تعیین شده برای پارامترها را مورد استفاده قرار می دهد و سپس آن را طوری ترجمه می کند که گویی یک پکیج معمولی بدون پارامتر است. سؤال : اگر تعریف نوع داده چندین بار نمونه سازی شود، این پیاده سازی ممکن است کارآمد نباشد، چرا؟ جواب: زیرا چند نسخه کپی از کل پکیج را ایجاد می کند که زیربرنامه های آن دوباره باید کامپایل شود. راه حل: در بخش چندریختی بحث می شود.
اما بحث اصلی : وراثت اگر بخواهیم اطلاعات موجود در یک بخش از برنامه ، در بخش های دیگر مورد استفاده قرار بگیرد باید از وراثت استفاده کنیم. وراثت: اخذ خواص و ویژگی های یک قطعه از برنامه توسط قطعه دیگر، بر اساس رابطه ای که بین این قطعات وجود دارد. شکل اولیه وراثت در قواعد حوزه مربوط به داده های ساخت یافته بلوکی وجود داشت ، اسامی مورد استفاده در بلوک داخلی ، ممکن است ازبلوک خارجی به ارث برده شوند. مثال زیر را ببینید: { int i,j; { float j,k; k = i +j; } }
وراثت و کلاس ها اگر رابطه بین کلاس A و کلاس B برقرار شود ، به صورت A=>B نوشته می شود و اشیایی از کلاس A به طور ضمنی به ارث برده می شوند و در B قابل استفاده اند. مثال : اگر شی X در کلاس A تعریف شده باشد و در کلاس B مجددا تعریف نشده باشد ، هر مراجعه به X درکلاس B ، از طریق وراثت ، به شی X کلاس A اشاره می کند. اگر داشته باشیم A=>B ، می گوییم A کلاس پدر یا ابرکلاس است و B کلاس وابسته ، فرزند یا زیرکلاس یا کلاس مشتق است. A جدبلافصل B است. اگرچند کلاس پدرمشترکی داشته باشند همزاد هستند و این فرزندان ، فرزندان بلافصل این پدر مشترک هستند.
وراثت و کلاس ها وراثت یگانه : کلاس فقط یک پدر دارد. وراثت چندگانه : کلاس بتواند چند پدر داشته باشد. U W Y X V A B D C وراثت چندگانه برای X وراثت یگانه
کلاس و بسته بندی راستی یادتون باشه: در C++ وراثت چندگانه وجود دارد ولی در جاوا ممکن نیست. کلاس ها در زبانهایی مثل C++ و اسمالتاک و جاوا با بسته بندی ارتباط تنگاتنگی دارند. یعنی کلاس ها معمولا بخشی دارندکه توسط کلاس دیگربه ارث برده می شود و بخش دیگری دارند که مخفی است.
کلاس و بسته بندی مثال (C++) در کلاس زیر: (اسامی بعد از public درخارج ازکلاس قابل استفاده و قابل ارث بری هستند) (اعلان های size و storage که بعد از private آمده اند ،فقط در داخل کلاس قابل دستیابی اند) Class intstack { public: intstack() { size = 0;} void push(int i) { size = size + 1; storage[size] = I; } int pop … Private: int size; int storage(100); }
بد نیست بدانیم که : متد چیست؟ هر انتزاع شامل توصیفگر داده ها و توابعی است که بر روی اشیایی از آن نوع عمل می کنند. این توابع متد نام دارند. سازنده چیست؟ تابعی که همنام کلاس است و هنگام ایجاد شی از آن کلاس، فراخوانی می شود.مثل intstack() در کلاس intstack . مخرب چیست؟ تابعی همنام با کلاس (که در c++ با ~ شروع می شود) ، مخرب کلاس نام دارد. این تابع هنگام از بین رفتن شیئی از آن کلاس فراخوانی می شود.
کلاس های مشتق وراثت در C++ و جاوا از طریق کلاس های مشتق انجام می شود. کلاس های زیر را درنظر بگیرید: Class elem { Public: elem() { v = 0; } void ToElem(int b) { v = b; } int fromElem().{ return v; } Private: int v; } کلاس elem شی داده نوع elem و کلاس ElemStack پشته هایی از اشیا آن نوع ایجاد می کند Class ElemStack: elem { public: ElemStack() { size = 0;} void push(elem i) { size = size + 1; storage[size] = i; } elem pop() { size = size - 1;return Storage[size + 1] } Private: int size; elem storage[100]; } ElemStack :کلاس مشتق Elem: کلاس پایه
پیاده سازی کلاس ها در کلاس مشتق ، فقط اسامی ارثی ، از کلاس پایه به فضای نام محلی کلاس مشتق اضافه می شود و اسامی عمومی برای کاربران آن کلاس قابل مشاهده اند. نمایش حافظه واقعی برای اشیای تعریف شده ، می تواند به طور ایستا ، توسط اعلان داده ها در تعریف کلاس تعیین شود. هر نمونه ای از کلاس ، حافظه داده ی مخصوص به خود را دارد که شامل داده ها و اشاره گرهایی به متدهای کلاس است .از این رو دو مدل پیاده سازی برای کلاس ها داریم: 1- روش کپی 2- روش اشتراک حافظه
پیاده سازی کلاس ها روش کپی : در این مدل هر نمونه ای از کلاس مشتق، حافظه داده ی مخصوص به خود را دارد که شامل داده ها و اشاره گرهایی به متدهای کلاس پایه نیز هست. اگر شیئی از کلاس پایه ای مشتق شود ، این وراثت توسط مترجم اداره می شود و حافظه واقعی آن شی حاوی تمام جزئیات پیاده سازی آن است. به عنوان مثال : c++ فقط از روش کپی استفاده می کند. روش اشتراک حافظه : در این روش همه اشیاء از کلاس مشتق ، از حافظه کلاس پایه استفاده می کند. خواص ارثی ، در کلاس مشتق تکرار نمی شوند. این مدل نیازمند نوعی اشتراک داده است. به طوری که تغییرات در شی کلاس پایه ممکن است منجربه تغییر در شی مشتق شود. این روش موجب استقاده بهینه از حافظه می شود.
اما مشکلی در اینجا وجود دارد؟؟؟ وراثت متدها وراثت متدها برای ایجاد اشیای جدید ، قدرت دیگری اعمال می کند که در بسته بندی موجود نیست. به عنوان مثال : مثال قبل را بسط می دهیم و زیربرنامه عمومی MyType را به کلاس ElemStack اضافه می کنیم که نام نوع را چاپ می کند:’’ I am type ElemStack’’. Void MyType() {printf(“I am type ElemStack \ n”)} اگر فرض کنیم نیاز به کلاس جدیدی به نام NewStack است تا مانند ElemStack رفتار کند ، اما شامل متد جدید peek باشد که عنصربالای پشته را برمی گرداند و پشته را نیز تغییر نمی دهد. می توان به جای تعریف مجدد کلاس NewStack از وراثت استفاده کرد: Class NewStack: ElemStack { Public: int peek() { return storage[size].FromElem()} } اما مشکلی در اینجا وجود دارد؟؟؟
آیا متد ارثی مشکل درست می کند؟ برای اشیاء کلاس NewStack ، متد MyType پیام ’’ I am type ElemStack’’ را چاپ می کند، زیرا تعریف متدارثی ازکلاس elemstack است. این مشکل را به دو طریق می توان حل کرد: 1. می توانیم متد MyType را در تعریف کلاس NewStack دوباره تعریف کنیم: Void MyType() {printf(“I am type NewStack \ n”)} 2. از تابع مجازی (virtual) استفاده شود.
کلاس پایه برای NewStack تابع مجازی: كلاس پايه مي تواند متدهايي داشته باشدكه همنام آن ها در كلاس هاي مشتق نيز موجود باشد. این متد را در كلاس پايه متد مجازي مي گوييم. به عنوان مثال : در تعریف کلاس ElemStack ، زیربرنامه MyType را به صورت زیر تعریف می کنیم: Virtual void TypeName() {printf(“ElemStack \ n ”)} Void MyType() {printf(“ I am type”, TypeName())} و در کلاس NewStack می توانیم TypeName را به صورت زیر تعریف می کنیم: Virtual void TypeName() {printf(“NewStack \ n ”)} مزیت نسبت به روش قبلی : به جای تکرار متدMyType درهرکلاس مشتق فقط یک تابع مجازی کوچک باید در هرکلاس مشتق تعریف شود. کلاس پایه برای NewStack زمانی که فراخوانی می شود به زیربرنامه ای مقید می شود که در زمان تعریف متد به آن مراجعه می شود.
کلاس های انتزاعی اگر قرار باشد از تعریف کلاس ها به صورت یک قالب استفاده کنیم به طوری که کلاس های دیگری از آن ساخته شوند از دو روش استفاده می کنیم: ابرکلاس انتزاعی : باید کلاس را طوری تغییر دهیم که دیگر نتوان از آن مستقیم شیی ساخت و اشیایی که از این کلاس استفاده می کنند باید از زیرکلاس مشتق شوند. به عنوان مثال : درC++ این کار را با اعلان TypeName به صورت تابع مجازی تهی انجام می دهیم: Virtual void TypeName() = 0; مثلا اگر این تابع را در ElemStack تعریف کنیم هیچ شی از آن ساخته نمی شود و هر کلاس مشتق باید تابع مجازی را دوباره تعریف کند تا نمونه ای از آن کلاس ایجاد شود.
کلاس های انتزاعی وراثت mixin : شکل دیگری از وراثت که درآن تفاوت بین کلاس پایه و مشتق جدید را تعریف می کنیم. برای این کار یک کلاس delta تعریف می کنیم که شامل تغییرات باشد. مثلا: کلاس ElemStack و کلاس مشتق NewStack را در نظر بگیرد: Deltaclass StackMod { Int peek() { return storage[size].FromElem();} سپس کلاس جدید خود را می توانیم به صورت زیر ایجاد کنیم: Class NewStack = class ElemStack + deltaclass StackMode امتیاز mixin: با اعمال کلاس delta به هرکلاسی می توانیم کلاس جدیدی ایجاد کرد. تمام صفات ElemStack را با تغییراتی که توسط کلاس StackMod اعمال شد به ارث می برد.
عمومیت متضاد اختصاصی شدن است مفاهیم انتزاع وراثت و انتزاع مکانیزمی برای انتقال اطلاعات بین اشیاء کلاس های مربوط ارائه می کند. اگر A=> B به معنای این باشد که B به A ربط دارد ، چهار نوع رابطه بین اشیاء A و B وجود دارد: اختصاصی شدن (specialization) : متداول ترین شکل وراثت است که اجازه می دهد شیء مشتق B خواص دقیقتری نسبت به آنچه که در A وجود دارد کسب کند. composite مثلا : پشته دقیقتر از داده مرکب و پشته صحیح دقیقتر از پشته است. NewStack حالت خاصی از کلاس ElemStack است. stack record عمومیت متضاد اختصاصی شدن است int stack Real stack …….
مفاهیم انتزاع... تجزیه (decomposition) : اصل تفکیک انتزاع به عناصرآن است. به عنوان مثال : پشته از دیدگاه خارجی متشکل از متغیر top و ازدیدگاه داخلی متشکل از storage[100] است که اسامی داخلی درخارج از تعریف کلاس ناشناخته اند. stack top Stotage[100]
مفاهیم انتزاع... نمونه سازی (installation): فرآیند ایجاد نمونه ای ازکلاس است. درواقع عملیات کپی است. مثالی از نمونه سازی : اعلان نمونه هایی از شیء کلاس دربرنامه C++ است. Stack A, B, C; stack Stack A Stack B Stack C مفهوم متضاد آن دسته بندی است. مثلا ما می توانیم A ، B و C را به عنوان نمونه هایی از کلاس stack دسته بندی کنیم.
مفاهیم انتزاع... انفرادی سازی (individualization) : در این حالت ، اشیای مشابه ، برای اهداف مشترکی دریک گروه قرار می گیرند. به عنوان مثال : ممکن است بین پشته ها دریک مترجم ، رکوردفعالیت یا جدول نماد وجود داشته باشد. C و پاسکال رکوردهای فعالیت را به صورت پشته پیاده سازی می کنند اما نقش رکورد فعالیت درآنها متفاوت است.گرچه ساختارهای آنها یکسان است. stack act record Symbol table c act record Pascal act record
چندریختی چند ریختی به معنای این است که نام یک زیربرنامه یا عملگر بر حسب انواع آرگومان ها و نتایج ، به هر تعدادی از تعریف توابع اشاره کند. چندریختی به توابعی اعمال می شود که آرگومان آنها میتواند خود یک نوع باشد. به عبارتی نوع آرگومان تابع چندریختی می تواند یکی از چند نوع باشد. به طورمثال : عملگر + هم براي جمع كردن اعداد اعشاري و هم براي جمع كردن اعداد صحيح به كار مي رود. 1 + 2 1.5 + 2.7
مثال : كلاس vector را به صورت يك كلاس قالب اعلان كرديم و برداري از آن ساختيم تا حدود آن كنترل شود: #include "iostream.h" #include "conio.h" #include "stdlib.h" template <class T> class vector { T *x; int low, high; public: vector (int l, int h) low = l; high = h; x = new T[high – low + 1]; }
پیاده سازی توابع چندریختی برای زبان هایی با نوع ایستا مثل ام ال یا C++ ، چندریختی پیچیدگی جدیدی را ایجاد نمی کند. اما زبان هایی که چندریختی پویا را اجازه می دهند(مثل لیسپ) منجر به مشکل می شود ، زیرا آرگومان تابع چندریختی باید درحین اجرای برنامه تعیین شود.
به پایان آمد این دفتر حکایت همچنان باقیست به پایان آمد این دفتر حکایت همچنان باقیست بدبختی آدمی ،از جهل نیست از تنبلی است با تشکر صمیمانه از صبر و حوصله همه شما