برنامه نویسی

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، زیرا او معتقد است که این قسمت وجود ندارد.

و همین است!

امیدوارم که شما توانسته اید مفهوم پلی مورفیسم را درک کنید. اگر سوالی دارید می توانید در نظرات بگذارید ، یا اگر می توانید با من تماس بگیرید.

مطالعات خوب ، و حتی بیشتر/

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا