پلی مرفیسم در برنامه نویسی چیست؟
پلی مرفیسم در برنامه نویسی چیست؟
راهنمای جامع و تشریح پلی مرفیسم در برنامه نویسی برای مبتدیان
ورود به دنیای برنامهنویسی شیءگرا یا همان Object-Oriented Programming با اصطلاحات و مفاهیم چالشبرانگیز متعددی همراه است که در نگاه اول ممکن است برای هر فرد مبتدی پیچیده و حتی ترسناک به نظر برسد. توسعهدهندگان تلاش میکنند تا با استفاده از الگوها و قوانین مشخص، کدهایی بنویسند که نه تنها در زمان حال به درستی کار کنند، بلکه در آینده نیز قابلیت توسعه و تغییر داشته باشند. یکی از ارکان اصلی این سبک از برنامهنویسی، مفهومی با نام چندریختی است که پایههای ساخت نرمافزارهای مدرن را تشکیل میدهد. زمانی که ما قصد داریم کدهای خود را به شکلی بنویسیم که انعطافپذیری فوقالعادهای داشته باشند، باید به سراغ این ویژگی برویم. در این مقاله تخصصی قصد داریم به صورت کاملا توصیفی و تشریحی بررسی کنیم که پلی مرفیسم در برنامه نویسی چیست و چگونه میتواند دیدگاه ما را نسبت به حل مسئله و طراحی نرمافزار به کلی متحول کند.
مقدمهای بر دنیای شگفتانگیز برنامهنویسی شیءگرا
پیش از آنکه بتوانیم به درک عمیقی از این واژه برسیم، باید بدانیم که رویکرد شیءگرایی اصلا با چه هدفی به وجود آمده است. در برنامهنویسی سنتی، کدها به صورت مجموعهای از دستورات و توابع پشت سر هم نوشته میشدند که مدیریت آنها در پروژههای بزرگ به شدت سخت و طاقتفرسا بود. با معرفی شیءگرایی، برنامهنویسان تصمیم گرفتند دنیای واقعی را درون کامپیوتر شبیهسازی کنند. در دنیای واقعی، ما با اشیاء مختلفی سر و کار داریم که هر کدام ویژگیها و رفتارهای خاص خود را دارند. برای مثال یک موجود زنده، یک خودرو، یا حتی یک حساب بانکی، همگی اشیایی هستند که میتوانند اطلاعاتی را در خود نگه دارند و کارهای خاصی را انجام دهند. در این دنیای شبیهسازی شده، اصولی مانند کپسولهسازی و وراثت به ما کمک میکنند تا اشیاء را تعریف کنیم و ویژگیهای آنها را به اشتراک بگذاریم. اما برای ایجاد یک تعامل پویا و هوشمندانه میان این اشیاء، به یک مفهوم اساسی دیگر نیاز داریم که همان بحث اصلی مقاله ماست.
ریشهیابی و تعریف اولیه: پلی مرفیسم چیست و از کجا آمده است؟
برای درک بهتر هر واژه تخصصی، بهترین کار بررسی ریشه لغوی آن است. این کلمه از زبان یونانی باستان وام گرفته شده است و از دو بخش مجزا تشکیل میشود. بخش اول «پلی» به معنای «چند» یا «بسیار» است و بخش دوم «مورف» به معنای «شکل» یا «فرم» میباشد. با ترکیب این دو متوجه میشویم که معنای لغوی آن «چندریختی» یا داشتن اشکال متعدد است. در زندگی روزمره ما مثالهای بیشماری از این مفهوم وجود دارد. یک انسان واحد را در نظر بگیرید؛ این فرد در محیط کار خود نقش یک کارمند یا مدیر را ایفا میکند، در خانه نقش یک همسر یا فرزند را دارد و در فروشگاه به عنوان یک مشتری رفتار میکند. این انسان در هر موقعیت و در مواجهه با شرایط مختلف، رفتار و فرم متفاوتی از خود نشان میدهد، در حالی که ماهیت و هویت اصلی او ثابت است. اکنون اگر بخواهیم بدانیم در دنیای کامپیوتر پلی مرفیسم چیست، باید همین تمثیل رفتاری چندگانه را به موجودیتهای درون کدهایمان نسبت دهیم که در بخشهای بعدی به تفصیل و با مثالهای ملموس آن را بررسی خواهیم کرد.
ورود به دنیای کدها؛ پلی مرفیسم در برنامه نویسی به چه معناست؟
اکنون وقت آن است که این مفهوم انتزاعی را وارد دنیای کامپیوتر کنیم. اگر بخواهیم یک تعریف دقیق ارائه دهیم، باید بگوییم که پلی مرفیسم در برنامه نویسی توانایی یک متغیر، تابع یا شیء برای گرفتن اشکال مختلف و نشان دادن رفتارهای متفاوت تحت یک نام واحد است. به زبان سادهتر، ما میتوانیم یک دستور یا پیام یکسان را به چندین شیء مختلف ارسال کنیم، اما هر یک از آن اشیاء بستہ به نوع و ماهیت خود، پاسخ متفاوتی به آن پیام واحد بدهند. در برنامهنویسی مدرن، این توانایی به شدت ارزشمند است، زیرا به ما اجازه میدهد کدی بنویسیم که به جای تمرکز بر جزئیات تکتک اشیاء، بر روی دستورات کلی تمرکز کند. شما میتوانید یک سیستم مرکزی طراحی کنید که با مجموعهای از اجزای مختلف ارتباط برقرار میکند، بدون اینکه نیازی داشته باشد دقیقا بداند هر جزء چگونه کار خود را انجام میدهد. این شفافیت و جداسازی وظایف، دقیقا همان چیزی است که پایداری پروژههای نرمافزاری بزرگ را تضمین میکند و از بروز خطاهای زنجیرهای در هنگام تغییر کدها جلوگیری مینماید.
بررسی ضرورتها: پلیمرفیسم چیست و چرا باید از آن استفاده کنیم؟
ممکن است یک فرد مبتدی از خود بپرسد که در صورت عدم استفاده از این ویژگی چه اتفاقی رخ میدهد؟ برای درک اینکه ضرورت استفاده از پلیمرفیسم چیست ، فضای یک برنامه را بدون وجود این قابلیت تصور کنید. فرض کنید شما نرمافزاری مینویسید که باید مساحت اشکال هندسی مختلف را محاسبه کند. اگر چندریختی وجود نداشته باشد، شما مجبور هستید برای دایره یک تابع به نام محاسبه مساحت دایره، برای مربع یک تابع به نام محاسبه مساحت مربع و برای مثلث تابعی دیگر تعریف کنید. هر بار که قصد دارید مساحت شکلی را در بخشی از برنامه حساب کنید، سیستم شما باید ابتدا با دستورات شرطی طولانی بررسی کند که با چه شکلی روبرو است و سپس تابع مخصوص به آن را صدا بزند. این کار باعث میشود کدهای شما پر از دستورات شرطی تو در تو شود که نگهداری و خطایابی آنها یک کابوس واقعی است. با استفاده از این قابلیت شیءگرایی، شما از نوشتن کدهای تکراری و پیچیده بینیاز میشوید و کدهایتان بسیار تمیزتر، خلاصهتر و قابل فهمتر خواهد بود.
یک مثال ساده و ملموس از دنیای واقعی برای درک بهتر موضوع
بیایید برای روشنتر شدن موضوع از یک مثال بسیار ساده و توصیفی استفاده کنیم که برای هر فرد مبتدی قابل درک باشد و نیازی به دانش سینتکسهای پیچیده برنامهنویسی نداشته باشد. فرض کنید در کدهای خود مفهوم جامعی به نام “حیوان” تعریف کردهاید و زیرمجموعههایی مانند “سگ”، “گربه” و “گاو” برای آن ایجاد نمودهاید. حال شما میخواهید تمام این حیوانات در برنامه شما صدایی از خود تولید کنند. شما یک فرمان کلی به نام “تولید صدا” را در نظر میگیرید. زمانی که برنامه شما فرمان “تولید صدا” را به شیء سگ ارسال میکند، صدای پارس کردن پخش میشود. زمانی که این فرمان دقیقا با همان نام به شیء گربه ارسال میشود، صدای میو میو خواهید شنید و به همین ترتیب برای گاو صدای متفاوتی تولید میگردد. در این فرایند، برنامه اصلی شما اصلا اهمیتی نمیدهد که حیوان مورد نظر از چه نوعی است و سیستم حنجره آن چگونه در کدهایش پیادهسازی شده است؛ برنامه فقط یک دستور مشترک صادر میکند و این اشیاء هستند که به صورت هوشمندانه و بر اساس ذات درونی خود، بهترین و مناسبترین رفتار را از خود بروز میدهند.
نگاه عمیقتر به مکانیزمها: تکنیکهای پیادهسازی پلی مرفیسم چیست
در دنیای مهندسی نرمافزار زمانی که میپرسیم تکنیکهای پیادهسازی پلی مرفیسم چیست ، معمولا به دو رویه کلی برخورد میکنیم که یکی در زمان اجرا و دیگری در زمان کامپایل برنامه اتفاق میافتد. نوع متداولتر آن که در زمان اجرا تصمیمگیری میشود، معمولا با کمک مفهوم وراثت و بازنویسی متدها شکل میگیرد. در این روش، شما یک کلاس والد دارید که دستوری کلی در آن نوشته شده است و کلاسهای فرزندی دارید که آن دستور را مطابق با نیاز خود بازنویسی یا اصلاح کردهاند. زمانی که برنامه در حال اجراست، سیستم به صورت کاملا پویا بررسی میکند که در حال حاضر با کدام فرزند در حال تعامل است و نسخه مربوط به همان فرزند را اجرا میکند. این قابلیت پویایی شگفتانگیزی به نرمافزار شما میبخشد، زیرا باعث میشود برنامه شما بتواند حتی با اشیایی که در آینده و مدتها پس از نوشته شدن هسته اصلی سیستم به کدهایتان اضافه میشوند نیز به درستی و بدون بروز خطا کار کند.
بررسی نوع دیگر: تغییر شکل رفتارها در زمان کامپایل شدن کدها
در کنار رفتار پویایی که در بخش قبل توضیح دادیم، جنبه دیگری نیز وجود دارد که در بسیاری از زبانهای برنامهنویسی پیادهسازی میشود و آن استفاده از یک نام مشترک با ورودیهای متفاوت است. فرض کنید شما تابعی برای جمع کردن اعداد نوشتهاید و نام آن را “محاسبه جمع” گذاشتهاید. شما میتوانید دقیقا با همین نام، چندین تابع دیگر در برنامه بنویسید، با این تفاوت که یکی از آنها دو عدد ریاضی دریافت کند، دیگری سه عدد دریافت کند و تابع سوم دو متن را به عنوان ورودی بگیرد تا آنها را به هم بچسباند. در اینجا با اینکه نام تمام دستورات شما کاملا یکسان است، اما کامپایلر یا مفسر زبان برنامهنویسی با نگاه کردن به مقادیری که شما به این توابع ارسال میکنید، متوجه میشود که منظور شما کدام نسخه از عملیات است. این مورد نیز یک فرم بسیار پرکاربرد از مفهوم چندریختی به شمار میرود که باعث میشود نیازی نداشته باشید دهها نام مختلف برای کارهایی که ذاتا شبیه به هم هستند حفظ کنید.
نقش کلیدی و کاربرد پلی مرفیسم در برنامه نویسی مدرن و توسعه وب
با توجه به گسترش روزافزون برنامههای تحت وب و نرمافزارهای پیچیده موبایلی، میتوان به جرات گفت که معماری هیچ نرمافزار استانداردی بدون بهرهگیری از این مفاهیم پیش نمیرود. در پروژههایی که شما قصد دارید از سیستمهای مدرن، لود سریع اطلاعات، و معماریهای پیشرفتهای نظیر برنامههای تکصفحهای یا تعاملات آنی با وبسوکتها استفاده کنید، الگوهای شیءگرایی به شدت کاربرد دارند. برای درک بهتر اینکه جایگاه پلی مرفیسم در برنامه نویسی در چنین سیستمهایی چیست، فرض کنید در یک پیامرسان در حال ارسال پیام هستید. نوع پیام میتواند متن، عکس یا ویدیو باشد. دکمه ارسال پیام فقط یک دستور “ارسال” را صادر میکند. اینکه پشت صحنه متن مستقیما ذخیره شود یا ویدیو ابتدا در سرور فشرده و سپس آپلود گردد و با وبسوکت برای شخص مقابل مخابره شود، بر عهده اشیای دریافتکننده دستور است. معماری اصلی پیامرسان نیازی ندارد برای هر نوع فایل منطق متفاوتی را در دکمه ارسال هندل کند و این یعنی رسیدن به اوج زیبایی و کارایی در تولید نرمافزارهای یکپارچه و بهینه.
پرسش و پاسخ ذهنی: پلیمرفیسم چیست و تفاوت آن با وراثت در کجاست؟
بسیاری از مبتدیانی که به تازگی شروع به یادگیری کردهاند این دو مفهوم را با هم اشتباه میگیرند و همواره میپرسند که مرز بین وراثت و پلیمرفیسم چیست و چگونه باید آنها را تفکیک کرد. برای روشن شدن این مرزها، توجه داشته باشید که وراثت صرفا فرایندی است که در آن یک شیء، ویژگیها و رفتارهای یک شیء دیگر را به ارث میبرد تا از نوشتن کدهای تکراری جلوگیری شود؛ دقیقا مانند فرزندی که رنگ چشم والدینش را به ارث میبرد. اما چندریختی، مفهومی فراتر از صرفا ارث بردن است. چندریختی به آن فرزند اجازه میدهد که با وجود به ارث بردن یک استعداد از والد خود، آن استعداد را به شیوه و سبک اختصاصی خودش پیادهسازی و اجرا کند. به عبارتی دیگر، وراثت به سوال “چه چیزهایی بین اجزای سیستم مشترک است؟” پاسخ میدهد و چندریختی به سوال “چگونه اجزای مشترک، رفتارهای متفاوت و منحصربهفردی در زمان عمل از خود نشان میدهند؟” جواب میدهد. این دو در کنار هم، بالهای پرواز یک معمار نرمافزار برای خلق سیستمهای پایدار به شمار میآیند.
گسترش سیستم و نگهداری آسان با درک عمیق این الگوها
مسئله نگهداری کد یا Maintenance یکی از پرهزینهترین بخشهای چرخه حیات نرمافزارهای امروزی است. فرض کنید مدیریت یک نرمافزار بزرگ بانکی را برعهده دارید و قرار است نوع جدیدی از کارت اعتباری با قوانین کسر کارمزد متفاوت به سیستم اضافه شود. اگر سیستم بر پایه اصول شیءگرایی منعطف طراحی نشده باشد، باید صدها فایل مختلف تغییر کرده و دستورات شرطی جدیدی برای شناسایی این فرمت جدید اضافه شود. اما اگر بدانیم مفاهیم کلیدی همچون پلیمرفیسم چیست و از پایه آن را رعایت کرده باشیم، تنها کاری که باید انجام دهیم ساختن یک کلاس جدید برای کارت جدید است. این کارت جدید خودش میداند که بر اساس دستور مشترک “کسر کارمزد” باید چه فرمولی را پیادهسازی کند. سیستم مرکزی بانک بدون هیچ دستکاری یا دریافت آپدیت سنگینی، کارت جدید را میپذیرد و روالها بدون کوچکترین اخلالی به کار خود ادامه میدهند. مقیاسپذیری نرمافزار به صورت مستقیم به این الگوها گره خورده است و درک توصیفی این رفتارها، اولین قدم در مسیر تبدیل شدن به یک برنامهنویس ارشد میباشد.
نتیجهگیری نهایی پیرامون پلی مرفیسم در برنامه نویسی
در پایان این مقاله جامع، متوجه میشویم که مفاهیم مهندسی نرمافزار برخلاف اسامی پیچیدهای که دارند، تماما بر اساس منطق و سادهسازی فرایندهای ذهنی ابداع شدهاند. یادگیری عمیق این که پلی مرفیسم در برنامه نویسی دقیقا چگونه عمل میکند، شما را از یک کدنویس ساده به یک حلکننده مسئله خلاق و یک طراح حرفهای تبدیل مینماید. به جای اینکه نگران یادگیری سینتکسهای دشوار یا حفظ کردن خطوط طولانی کد باشید، سعی کنید مفاهیم توصیفی که در این مقاله شرح داده شد را در ذهن خود تجسم کنید. زمانی که با دیدن پدیدههای دنیای واقعی بتوانید رفتارهای چندریختی، عملکردهای مشترک با خروجیهای متفاوت و استقلال رفتار هر شیء را درک کنید، پیادهسازی آنها در هر زبانی، از پایتون و پیاچپی گرفته تا جاوااسکریپت و سیشارپ، تنها مستلزم دانستن چند کلمه کلیدی ساده در محیط برنامهنویسی خواهد بود. امیدواریم این توضیحات تشریحی توانسته باشد مسیری روشن برای درک این مفهوم جذاب برای شما عزیزان فراهم آورد.