آموزش گام به گام #C (جلسه هجدهم: Overload کردن عملگرها)
1398/01/22 10:56 , میلاد صاحب نظر

آموزش گام به گام #C (جلسه هجدهم: Overload کردن عملگرها)

هدف برنامه‌نویس جلب رضایت کاربر نهایی است. اما اگر برنامه‌ای که می‌نویسیم به قدری پیچیده باشد که کاربر متوجه نحوه استفاده از برنامه نشود آنگاه چه می‌کنید؟ overload کردن عملگرها در این زمینه به ما کمک می‌کنند. با ما همراه باشید!

جلسه اول: آغاز کار با #C جلسه ششم: namespaceها جلسه یازدهم: اندیس گذار یا indexerها جلسه شانزدهم: استفاده از اتریبیوت‌ها جلسه بیست و یکم: متدهای بی‌نام یا anonymous
جلسه دوم: عملگرها، نوع‌ها و متغیرها جلسه هفتم: مقدمه‌ای بر کلاس‌های #C جلسه دوازدهم: ساختار یا structها جلسه هفدهم: enumها جلسه بیست و دوم: موضوعاتی در مورد نوع در #C
جلسه سوم: عبارات کنترلی - گزینشی جلسه هشتم: وراثت کلاس در #C جلسه سیزدهم: واسط یا interfaceها جلسه هجدهم: عملگرهای overloading جلسه بیست و سوم: کار با نوع‌های nullable
جلسه چهارم: عبارات کنترلی - حلقه‌ها جلسه نهم: چندریختی جلسه چهاردهم: مقدمه‌ای بر delegateها و رویدادها جلسه نوزدهم: کپسوله‌سازی  
جلسه پنجم: متدها جلسه دهم: ویژگی یا propertyها جلسه پانزدهم: مقدمه‌ای بر کنترل خطا یا exception جلسه بیستم: مقدمه‌ای بر generic collectionها  

در این جلسه، چگونگی Overload کردن عملگرهای #C را نشان می‌دهیم. اهداف ما در این جلسه عبارت‌اند از:

  • درک معنی Overload کردن عملگر
  • تشخیص اینکه چه زمانی برای Overload کردن یک عملگر مناسب است
  • آموختن چگونگی Overload کردن یک عملگر
  • آشنایی با قوانین Overload کردن عملگر

در مورد Overload کردن عملگر

در جلسه دوم، آموختید که در #C چه عملگرهایی وجود دارند که برخی از آن‌ها عبارت بودند از + (به علاوه)، - (منها)، ^ (انحصار یا) و غیره. عملگرها برای نوع‌های مخصوص #C تعریف شده‌اند، اما مورد استفاده آن‌ها فقط این نیست.

می‌توانید عملگرها را به نوع‌های خاص خودتان نیز اضافه کنید و این امکان را فراهم کنید تا عملگرها با آن‌ها مشابه با نوع‌های خاص #C رفتار کنند.

برای درک نیاز به Overload کردن عملگر، تصور کنید که می‌خواهید در برنامه خود یک عملیات ماتریس ریاضی اجرا کنید. می‌توانید دو آرایه ۲ بعدی نمونه‌سازی کنید و کاری که می‌خواهید را انجام دهید.

به هر حال، باید قابلیت قابل استفاده مجدد بودن را به رفتار ماتریس اضافه کنید. چون بالاخره در آینده نیاز پیش می‌آید که در برنامه‌های دیگر از این ماتریس استفاده کنید و وقتی این نیاز پیش آمد، می‌توانید از مزیت این حقیقت که قبلاً یک بار کد آن را نوشته‌اید، بهره‌مند شوید. پس برای این منظور، باید یک نوع جدید ایجاد کنید.

بنابراین، یک نوع Matrix (ماتریس) ایجاد می‌کنید، که می‌تواند یک کلاس یا یک Struct باشد. حالا نحوه مورد استفاده قرار گرفتن این ماتریس را تجسم کنید.

شما باید دو یا تعداد بیشتری از نمونه‌های ماتریس را با داده‌ها مقداردهی کنید و سپس یک عملیات ریاضی با آن‌ها انجام دهید (مثل جمع کردن یا هر عملیات دیگری). برای انجام موفق عملیات ریاضی، می‌توانید یک متد ()Add()، DotProduct و متدهای دیگر اضافه کنید. استفاده از کلاس‌ها چیزی شبیه به این است:

یا

یا حتی بدتر:

مشکل استفاده از متدهایی مانند این متد، این است که بسیار سخت، طولانی و برای حل مشکلی که شما با آن مواجه هستید واقعاً غیر طبیعی هستند. خیلی آسان‌تر می‌شد، اگر برای عملیات جمع یک عملگر + و برای عملیات ضرب یک عملگر * داشتیم. مثال زیر، Syntax چگونگی استفاده از عملگرها را نشان می‌دهد:

یا

یا حتی بهتر:

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

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

علاوه بر این، اگر کاربران اصلی برنامه شما ریاضی‌دان و دانشمندان باشند، مسلماً استفاده از عملگرهای رایج برای آن‌ها خیلی آشنا‌تر و طبیعی‌تر جلوه خواهد کرد.

چه موقع نباید از روش overload کردن عملگر استفاده کرد؟

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

در مثال بالا استفاده از آن عملگرها با نوع Matrix منطقی بود. این مثال دقیقه مشابه با دلیل منطقی بودن عملگرها برای نوع‌های مخصوص #C مانند int و float بود. به هر حال، توجه کنید که استفاده نابجا از عملگرها و پیاده‌سازی‌های پیچیده‌ای که درکشان برای همه (به خصوص خود نویسنده کد) سخت می‌باشد، خیلی آسان است.

برای درک یک پیاده‌سازی بد، یک کلاس Car را در نظر بگیرید که به پیاده‌سازی‌ای نیاز دارد که شما را قادر سازد خودرو را در گاراژ پارک کنید. اشتباه بزرگی‌ است که فکر کنید پیاده‌سازی زیر یک روش هوشمندانه است:

این یک کد بد است. اگر تا به حال تحریک شده‌اید که کاری مانند کد بالا انجام دهید، خب دیگر این کار را نکنید. هیچ‌کس نمی‌تواند واقعاً متوجه شود که آن کد چه معنایی دارید و مسلماً کسی هم فکر نمی‌کند که روش آن هوشمندانه باشد.

علاوه بر این، این کد به قابلیت رسیدگی و نگهداری برنامه نیز آسیب می‌رساند، چون درک اینکه کد چه کاری انجام می‌دهد خیلی سخت است. حتی با اینکه یک کامنت در کد قرار دارد، باز هم کمک زیادی نمی‌کند و اگر حتی کامنت هم وجود نداشت، دیگر درک مفهوم اضافه کردن یک Car به یک Garage واقعاً سخت و مشکل می‌شد.

ایده جدید این است: استفاده از عملگرها در موقعیت‌هایی که استفاده از آن‌ها درک بیشتری فراهم کرده و یک نوع کد نویسی ساده‌تر به وجود می‌آید.

پیاده‌سازی یک عملگر overload شده

یک Syntax که در آن یک عملگر overload شده پیاده‌سازی می‌شود، تشابه خیلی زیادی به یک متد static با چند exception (استثناء) دارد. شما باید از کلیدواژه operator استفاده کنید و علامت عملگر overload شده را مشخص کنید. این مثال ساختاری از چگونگی پیاده‌سازی عملگر ضرب (dot product) می‌باشد:

توجه کنید که متد static است. بعد از مشخص کردن نوع بازگشتی (که در این مثال Matrix می‌باشد) از کلیدواژه operator استفاده می‌شود. در ادامه کلیدواژه operator، علامت عملگر قرار می‌گیرد و سپس مجموعه‌ای از پارامترها قرار می‌گیرند که قرار است عملیات روی آن‌ها انجام شود.

لیست ۱-۱۸  مثال کاملی از چگونگی پیاده‌سازی و استفاده از یک عملگر overload شده را نشان می‌دهد.

لیست ۱-۱۸. پیاده‌سازی یک عملگر overload شده: Matrix.cs

کلاس Matrix در لیست ۱-۱۸ درست مشابه با مثال ساختاری عملگر dot product، شامل یک عملیات overload برای عملگر + می‌باشد. برای راحتی شما، من بخش پیاده‌سازی overload را در کد زیر جداگانه آورده‌ام:

عملگر، Static است که تنها حالت ممکن می‌باشد و باید این‌گونه تعریف شود، چون عملگر متعلق به نوع است و نه یک نمونه یا instance خاص. در هنگام پیاده‌سازی overloadهای عملگر باید از چند قانون پیروی کنید.

چیزی که باعث می‌شود یک کاراکتر به عنوان عملگر شناخته شود، استفاده از کلیدواژه operator است که بعد از آن علامت + قرار گرفته است. نوع هر دو پارامترها  همان نوع کلی overload یعنی Matrix است. پیاده‌سازی overload سازی عملگر، یک instance جدید از نوع بازگشتی ایجاد می‌کند و عملیات جمع ماتریس را انجام می‌دهد.

قوانین عملگر

وقتی قصد overload سازی عملگرها را دارید، #C شما را به رعایت چند قانون مجبور می‌کند. یک قانون این است که شما باید overloadسازی عملگر را در همان نوعی که فرآیند از آن استفاده می‌کند، پیاده‌سازی کنید. این یک قانون منطقی است، چون باعث می‌شود که آن نوع یک نوع مستقل باشد.

قانون دیگر این است که شما باید عملگرهای اختصاص یا تطابق را نیز پیاده‌سازی کنید. برای مثال، اگر عملگر == را overload کنید، باید همچنین عملگر =! را نیز پیاده‌سازی کنید. همین حرف برای =< و => نیز صدق می‌کند.

وقتی یک عملگر پیاده‌سازی می‌کنید، عملگر مرکب یا چند جزئی آن نیز عمل می‌کند. برای مثال، چون عملگر + برای نوع Matrix پیاده‌سازی شده است، می‌توانید همچنین از عملگر =+ روی نوع‌های Matrix نیز استفاده کنید.

خلاصه

Overload کردن عملگر در هنگام استفاده از عملگرها، به شما اجازه می‌دهد تا نوع‌هایی که همانند نوع‌های خاص #C رفتار می‌کنند را پیاده‌سازی و استفاده کنید. حتماً به روشی از عملگرها استفاده کنید که برای نوعی که به کار برده‌اید طبیعی و قابل درک باشد.

Syntax برای پیاده‌سازی عملگرها شباهت زیادی به یک متد Static دارد، اما شامل کلیدواژه operator و علامت عملگر به عنوان شناساگر می‌باشد. علاوه بر این، برای استفاده از عملگرها قوانینی وجود دارند (مانند حفظ تناسب) که باعث به وجود آمدن نوع‌های امن و کامل می‌شود.

منبع: C#-Station

جلسه بعد                                                                جلسه قبل

 مطالب مرتبط

 مقدمه ای بر زبان برنامه نویسی #C و پلتفرم NET Framework.
7 دلیل منطقی برای آموختن #C
 طبقه بندی زبان های برنامه نویسی
به دست آوردن Exceptionها در #C و یافتن همه خطاها
 LINQ(زبان جستجوی یکپارچه)
برنامه نویسی شیءگرا چیست؟

از آخرین دوره های آموزشی و تخفیف ها مطلع شوید

با تکمیل فرم زیر ، از اخبار و اطلاعات به روز برنامه نویسی و تکنولوژی عقب نمانید

آخرین مطالب

آموزش جامع SQL Server (جلسه ۱۲)
آموزش جامع SQL Server (جلسه ۱۲)

دستور UPDATE در SQL Server برای تغییر داده‌های موجود در یک جدول، از دستور UPDATE به شکل زیر استفاده ...

آموزش جامع SQL Server (جلسه ۱۵)
آموزش جامع SQL Server (جلسه ۱۵)

دستور DROP TABLE در SQL Server گاهی، لازم است یک جدول که دیگر استفاده‌ای ندارد را حذف کنید. برای ...

آموزش جامع SQL Server (جلسه ۳۵: Window Functionها – بخش ۲)
آموزش جامع SQL Server (جلسه ۳۵: Window Functionها – بخش ۲)

بخش اول از آخرین مبحث دوره جامع آموزش SQL Server در جلسه قبلی بررسی شد. این مبحث که ...

آخرین دیدگاه ها

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

فرم ارسال نظرات