Polimorfismo – جامعه dev

مقدمه
خوش آمدید! امروز می خواهم کمی در مورد پلی مورفیسم بنویسم ، موضوعی که قرار نبود آنقدر پیچیده باشد ، اما به نظر می رسد برای محبوبیت زبانهایی که در نهایت انجام برخی کارها را انجام می دهند “به طور ضمنی ، سحاب به نظر می رسد ، گاهی اوقات مانع درک برخی از مفاهیم می شود.
یادگیری کارآیی x
غیرقابل انکار است که در فرآیند ساخت نرم افزار ، از یک زبان استفاده کنید پیتون می تواند توسعه را بسیار ساده تر کند ، و باعث می شود زمان زیادی به دست آورید و هنگام ایجاد یک موانع غیر ضروری را به دست آورید پروژه واقعیبشر با این حال ، برخی از مفاهیم اساسی درک در مورد برنامه نویسی وجود دارد ، که در نهایت توسط زبانهایی مانند پایتون برای پیروزی “پنهان” می شوند بهره وری و دریافت کنید کد منبع آسان تربشر به همین دلیل ، اغلب برای کارآموزی این می تواند یک آبخیزداری انتخابی باشد که “جزئیات کمتری را پنهان می کند” زیرا باعث می شود شما “آگاه تر” از آنچه اتفاق می افتد بدون انتزاع زیاد باشد.
پلی مورفیسم چیست
به طور خلاصه ، پلی مورفیسم یک اصل است که به روشهای زیر کلاس اجازه می دهد تا از طریق یک کلاس مادر (سوپر کلاس) فراخوانی کنند.
توضیح
برای درک چندشکلی در حقیقت، لازم است که قبلاً برخی از مفاهیم دیگر مانند مفهوم میراث، و مفهوم نشانگرها، علاوه بر مفاهیم دیگری که من در اینجا ارائه خواهم داد ، مانند برش شیءبشر
برای شروع ، کد زیر را که در C ++ نوشته شده است ، یادداشت کنید
توجه: اگر به شما عادت نداشته باشید ، هیچ نحوی C ++ به آن پیوست نشده است ، لحظه ای که من این مطالب را می نویسم ، من کاملاً به زبان عادت ندارم ، با این حال ، من برای نشان دادن مفهوم پلی مورفیسم ایده آل است. اگرچه شما در C ++ برنامه ریزی نمی کنید ، اما باید بتوانید به اندازه کافی آنچه را که برای پیروی از توضیحات اتفاق می افتد درک کنید.
#include
class Base
{
public:
void method()
{
std::cout << "I am a Base method.";
}
};
class Derivative: public Base
{
public:
void method()
{
std::cout << "I am a Derivative method.";
}
};
int main()
{
Base *baseObject = new Base();
baseObject->method();
return 0;
};
توضیح مختصری درباره آنچه در اینجا اتفاق می افتد. ما کد را با شروع کردیم #include
این شامل کتابخانه هایی با اشیاء ورودی و خروجی استاندارد (ورودی/خروجی یا I/O ، بنابراین “IO”) است. ما این کار را کردیم تا در دسترس باشد cout
(خروجی C).
اگر علاقه مند هستید می توانید اطلاعات بیشتری در مورد کتابخانه پیدا کنید
iostream
اینجا یا بیشتر در موردcout
در اینجا
پس از آن ما دو کلاس ایجاد کردیم ، یک کلاس Base
و یک کلاس Derivative
(مشتق شده) که رانش طبقه Base
(یا ارث، اگر ترجیح می دهید چنین بگویید).
هر دو کلاس روش عمومی یکسان دارند method()
که می گوید روش متعلق به کدام کلاس است.
آیا Python AO C ++
اگر در پیگیری توضیحات به دلیل نحو C ++ مشکل دارید و به پایتون عادت کرده اید ، سعی می کنم کمی چیزها را روشن کنم.
class Derivative: public Base
این معادل آن خواهد بودclass Derivative(Base)
EM Python.std::cout<<"Hello World"
این معادل آن خواهد بودprint("Hello World")
پایتون- ای
void
در مقابل اعلامیه روشها به این معنی است که عملکرد هیچ چیزی را بر نمی گرداند. در C ++ باید در اعلامیه عملکرد نوع داده هایی که باز می گردد تعریف کنیم و باطل کردن اگر او چیزی برنگردد (main()
از مثال ما ، 0 را برمی گرداند ، بنابراین ما او را با او اعلام می کنیم در نظر گرفتن).
اکنون در عملکرد ما main()
، ما یک اشاره گر از نوع ایجاد کردیم Base
این به منطقه ای از حافظه اشاره دارد که در آن ما با یک شیء کلاس اختصاص می دهیم و اشغال می کنیم Base
بشر
وقتی کد را کامپایل و اجرا می کنیم ، نتیجه زیر را داریم:
I am a Base method.
تا آن زمان همه چیز منطقی است ، ما یک شیء داریم Base
تماس با روش کلاس Base
، همه خیلی خوب!
اگر کلاس را مبادله کنیم Derivative
، نتیجه باید متفاوت باشد.
int main()
{
Derivative *derivativeObject = new Derivative();
derivativeObject->method();
return 0;
};
توجه: من فقط برش کد را در مورد عملکرد نشان می دهم
main()
، نه برای آلودگی تجسم ، اگر در هر زمان دیگری از بقیه کد را تغییر دهم ، آنچه را که تغییر کرده است نمایش می دهم ، زیرا در اینجا فقط عملکرد را در اینجا جابجا کردم.main
من فقط آن را نشان می دهم ، فرض کنید که بقیه کد همان باری است که من آن را نشان دادم.
نتیجه این زمان به شرح زیر است:
I am a Derivative method.
ایده آل ، ما یک شیء از Base
و روشی که او نامید کلاس بود Base
، سپس ما یک شیء از Derivative
و روشی که او نامید کلاس بود Derivative
بشر
اما اگر موارد زیر را انجام دهیم چه اتفاقی می افتد:
int main()
{
Base *derivativeObject = new Derivative();
derivativeObject->method();
return 0;
};
تنها تغییری که من ایجاد کردم این بود نوع اشاره گر derivativeObject
به Base
بشر
اکنون ما یک مشکل داریم … نوع نشانگر می گوید که او به یک شیء اشاره می کند Base
، با این حال ، آنچه ما در حافظه قرار دادیم یک موضوع بود Derivative
بشر و حالا؟
اگرچه اشاره گر به عنوان نوع اعلام می شود Base
، آنچه واقعاً در حافظه ذخیره می شود یک موضوع است Derivative
، بنابراین وقتی روش را فراخوانی می کنیم ، این روش کلاس خواهد بود Derivative
، درست است؟
اشتباه! نتیجه این است:
I am a Base method.
اما چرا؟
خوب ، برای درک آنچه در اینجا اتفاق می افتد ، ما باید کمی از آنچه در آن اتفاق می افتد درک کنیم خاطره در طول اجرای برنامه ما.
وقتی ما یک شیء ایجاد می کنیم Derivative
و ما روش شما را صدا می کنیم method()
، ما نتیجه روش Derivative
، همانطور که انتظار می رفت. با این حال ، این اتفاق نیفتاد زیرا ما یک روش دیگر را رد و بدل کردیم ، هر دو در حافظه ذخیره شدند.
اما ممکن است تعجب کنید که چرا جهنم به روش اولویت می دهد Derivative
روش Base
وجود دارد ، مقرون به صرفه است و همین نام را دارد و این اتفاق می افتد زیرا به دنبال انجام عملکرد موجود در خاص ترین دامنه ممکن است. او به دنبال روش است method()
در کلاس Derivative
، اگر پیدا کردید که اجرا می شود ، اگر آن را پیدا نکردید که به دنبال کلاس مادر است Base
اگر متوجه شدید که اجرا می شود ، اگر متوجه نشده اید ، خطایی را برمی گرداند زیرا شما روشی خوانده اید که وجود ندارد.
با این همه می خواهم به این نکته برسم که هر دو در حافظه هستند ، هر دو چیز در کلاس Base
و همچنین Derivative
آنها به صورت توالی در حافظه ضبط می شوند.
فقط قبل از آن ، من نشانگر نوع را تعریف کرده بودم Derivative
، و اکنون من نوع را تعریف کردم Base
، که باعث شد او موضوع من را به عنوان تفسیر کند Base
، حتی بودن از نوع Derivative
بشر
“سلام ، اما اگر شما شی دارید
Derivative
در حافظه ، چرا نشانگر تظاهر کردن که او فقط چیزهایی از آن داردBase
؟
در واقع او وانمود نمی کند ، ما کسی هستیم که وقتی گفتیم این یک موضوع است ، او را فریب می دهیم Base
بشر من مثالی ایجاد می کنم که این مسئله را واضح تر می کند.
در حافظه ، ما فقط یک هرج و مرج عالی داریم صفر اشمیه اوج، اشاره گر فقط می تواند این داده ها را بازیابی کند زیرا می داند از کجا شروع کند و از کجا متوقف شود.
در مثال زیر ، همه اعداد را نادیده بگیرید.
بیایید تصور کنیم که کلاس Base
داده ها را دارد ابا، و کلاس Derivative
گله Base
و داده های خاص خود را دارد کیت، با هم آنها کلمه را تشکیل می دهند اووکادو، زیرا در حافظه ابتدا چیزهای کلاس مادر (TAB) ایجاد می شود و بعد از کلاس دختر (CATE). بنابراین در وسط حافظه چیزی شبیه به آن خواهیم داشت:
9 8 7 3 2 در پیش دادن 8 9 2 3 7 2 8 3
“آووکادو” ما در موقعیت ششم این دنباله شروع می شود و دارای 7 نامه است ، با این اطلاعات می دانیم کلاس کجا است Derivative
این شروع می شود (در موقعیت ششم) و جایی که به پایان می رسد (بعد از 7 حرف).
با این حال ، اگر Derivative
7 حرف دارد ، برخلاف Base
، که در مثال ما فقط 3 حرف دارد.
اگر نشانگر ، دانستن اینکه داده های ما در آن شروع می شود ششم، دریابید که این یک هدف است Base
، او فقط سه حرف اول را خواهد گرفت “ابا“
توجه داشته باشید که “کیت“این همچنان وجود دارد ، با این حال ، اشاره گر ما فکر می کند که شیء ما فقط 3 حرف دارد ، بنابراین او هنگام ورود به سوم ، متوقف می شود. عقیده که “کیت“این وجود ندارد.
و این چه ارتباطی با مثال قبلی دارد؟
بیایید “آووکادو” را برای شیء خود تغییر دهیم Derivative
با روش method()
بشر
شما قبلاً این را درک کرده اید Derivative
چیزهایی از Base
از نظر Derivative
، و اینکه آنها به صورت توالی در حافظه ثبت می شوند.
تمام آنچه باقی مانده است با مثال ما در ارتباط است “اووکادو“
بیایید کد را از سر بگیریم:
int main()
{
Base *derivativeObject = new Derivative();
derivativeObject->method();
return 0;
};
در این کد ، ما در حافظه من یک موضوع را ضبط می کنیم Derivative
، و ما یک اشاره گر را به این منطقه از حافظه نشان می دهیم ، اما ما به اشاره گر خود می گوییم که این یک هدف است Base
بشر
همانطور که در تصویر بالا نشان داده شده است ، ما مواردی را داریم Base
در یک موضوع از Base
، و هر دو Base
اشمیه Derivative
هدف نیست Derivative
بشر
اگر به اشاره گر خود بگوییم که این یک هدف است Base
، او اندازه یک شیء این کلاس را خواهد دید و از موقعیتی که می داند شروع می شود ، و با خواندن داده ها به جایی که از لحاظ نظری یک شی را با اندازه یک شیء پایان می دهد Base
بشر
به یاد داشته باشید که در مثال آووکادو ، سوپر کلاس ما فقط حروف “Tab” را داشت؟ این دقیقاً همان چیزی است که اکنون اتفاق می افتد ، ما به اشاره گر می گوییم که شیء کوچکتر از آن است که واقعاً باشد ، بنابراین فقط بخشی از این شی را می خواند.
این مفهوم همان چیزی است که ما می نامیم برش شیءبشر
خوب ، اما در مورد پلی مورفیسم چیست؟
شما فهمیدید که چگونه نشانگرها کار می کنند و می فهمید که چگونه کار آنها باعث ایجاد می شود برش شیءبشر حال چگونه این با پلی مورفیسم ارتباط دارد؟
در پلی مورفیسم ، تقریباً می توانیم بگوییم که می خواهیم برعکس انجام دهیم میراثبشر
در میراث ما می خواهیم از طریق یک شیء کلاس دختر ، از یک روش کلاس مادر استفاده کنیم ، در چند شکل ما می خواهیم بتوانیم از طریق کلاس مادر ، به یک روش کلاس کلاس دسترسی پیدا کنیدبشر
و چگونه این کار را انجام دهیم؟
جدول مجازی
کامپایلر C ++ مکانیسمی دارد که به شما امکان می دهد بدانید که شیء به فضای حافظه چه چیزی اختصاص داده شده است ، حتی اگر با نوع نشانگر مخالف باشد. در حال حاضر فرض کنید که این مکانیسم وجود دارد ، اگر می خواهید اطلاعات بیشتری کسب کنید ، می توانید مقاله ای درباره جدول مجازی در اینجا پیدا کنید.
در این روش می توانیم روشها را به عنوان مجازی علامت گذاری کنیم و روشی را به عنوان یک کلاس مشتق می نامیم.
#include
class Base
{
public:
virtual void method() // alternar o "virtual" alterna o resultado
{
std::cout << "I am a Base method.";
}
};
class Derivative: public Base
{
public:
void method()
{
std::cout << "I am a Derivative method.";
}
};
int main()
{
Base *derivativeObject = new Derivative();
derivativeObject->method();
return 0;
};
و نتیجه این است:
I am a Derivative method.
توجه داشته باشید که من کلمه کلیدی را درج می کنم virtual
در روش کلاس Base
بشر وقتی این کار را انجام می دهم ، تمام کلاس هایی که این کلاس را به ارث می برند ، این روش را به صورت مجازی مشخص می کنند ، حتی اگر غرق شود.
در عمل ، آنچه اتفاق می افتد وقتی که ما روش را فراخوانی می کنیم method()
:
- کامپایلر تأیید می کند که آیا این روش وجود دارد ، تأیید می کند که در کلاس پایه وجود دارد.
- کامپایلر می یابد که این یک روش مجازی است و از طریق جدول مجازی، کشف می کند که یک شیء
Derivative
با حتی اگر نشانگر بگوید این استBase
- کامپایلر در حال درمان این شی به عنوان شیء زیر کلاس است
Derivative
، همانطور که در حافظه است ، برای تماس با روشDerivative
بشر
من می فهمم ، اما این برای چیست؟
چندین برنامه کاربردی برای پلی مورفیسم وجود دارد ، از جمله اجرای اصل باز انجام دادن محکم می توان از طریق آن انجام شد.
اما ما لازم نیست که خودمان را به آن محدود کنیم. به یاد می آورد وقتی گفتم اگر نشانگر می گوید این یک هدف است Base
، او نمی داند که چیزهای بیشتری وجود دارد (چیزهای دیگر Derivative
) آنجا؟ این باعث می شود که او این داده ها را ننوخته باشد ، اما باعث می شود که وی نیز پاک نشود ، زیرا او معتقد است که او جزئی از شی نیست.
و اگر سعی کنیم یک شیء را پاک کنیم Derivative
او را صدا می کند Base
، آنچه اتفاق خواهد افتاد این است که ما فقط محتوای آن را که مربوط به کلاس است پاک می کنیم Base
، بقیه در حافظه ادامه خواهند یافت و بدتر ، برنامه این را نمی داندبشر تنها کسی که در این داستان است می داند که شیء ما را پاک کردیم نقطه، و او قسمت انحصاری را پاک نکرد Derivative
، زیرا او معتقد است که این قسمت وجود ندارد.
و همین است!
امیدوارم که شما توانسته اید مفهوم پلی مورفیسم را درک کنید. اگر سوالی دارید می توانید در نظرات بگذارید ، یا اگر می توانید با من تماس بگیرید.
مطالعات خوب ، و حتی بیشتر/