در بحث های قبلی، ما قبلاً Interfaces و Abstract Classes را در عمل دیده بودیم. اکنون، اجازه دهید اجرای زنده هر سه را در مورد یک مورد استفاده ببینیم. در انتها نیز شاهد تفاوت های مشابه خواهیم بود. و سپس انتخاب می کنید که برای شما مناسب تر است.
اجازه دهید ابتدا در مورد کلاس ساده ساده بحث کنیم. در زیر کلاس ساده برای محاسبه مساحت و محیط نوشته ام.
- using System;
- namespace Interface_Demo.Lib
- {
- public class BaseClass
- {
- public int Sides
- {
- get;
- set;
- }
- public int Length
- {
- get;
- set;
- }
- //To fill in these props
- public BaseClass(int sides, int length)
- {
- Sides = sides;
- Length = length;
- }
- //Calculate Perimeter. Number of sides * Length of each side
- public int CalcPerimeter()
- {
- return Sides * Length;
- }
- //Area differs for different object. Hence, it is kept virtual method to get overriden
- //in derived class
- public virtual int CalcArea()
- {
- throw new NotImplementedException();
- }
- }
- }
در این مثال، من اجرای دقیق محاسبه محیط را حفظ کردهام، اما محاسبه مساحت یک روش مجازی است زیرا اشیاء مختلف محاسبه مساحت متفاوتی خواهند داشت، بنابراین باید منحصراً در کلاس مشتق شده پیادهسازی شود. حال، اجازه دهید به کلاس مشتق شده برای همین نگاه کنیم.
- using System;
- namespace Interface_Demo.Lib
- {
- public class Square: BaseClass
- {
- public Square(int sides, int length): base(sides, length)
- {}
- public override int CalcArea()
- {
- return Sides * Length;
- }
- }
- }
در اینجا، روش مجازی راه خود را پیاده سازی کرد. حالا بیایید برنامه اصلی را برای همان نگاه کنیم.
- using Interface_Demo.Lib;
- namespace Interface_Demo.Console
- {
- class Program
- {
- static void Main(string[] args)
- {
- var square = new Square(4, 4);
- DisplayDimensions("Square", square);
- System.Console.ReadLine();
- }
- //dynamic key will resolve an object at runtime. very useful keyword
- private static void DisplayDimensions(string objectType, dynamic square)
- {
- System.Console.WriteLine("Displaying Dimensions of " + objectType);
- System.Console.WriteLine("Number of Sides:- " + square.Sides);
- System.Console.WriteLine("Length of Each Side:- " + square.Length);
- System.Console.WriteLine("Area of " + objectType + " is " + square.CalcArea());
- System.Console.WriteLine("Perimeter of " + objectType + " is " + square.CalcPerimeter());
- System.Console.WriteLine("==============================================================");
- }
- }
- }
حالا وقتی برنامه بالا رو اجرا میکنم خروجی زیر رو میده.
این فقط در مورد کلاس ساده ساده بود. حال، اجازه دهید به همین مثال با اجرای کلاس انتزاعی نگاه کنیم. در زیر کلاس انتزاعی برای همان است.
- namespace Interface_Demo.Lib
- {
- public abstract class AbstractBaseClass
- {
- public int Sides
- {
- get;
- set;
- }
- public int Length
- {
- get;
- set;
- }
- //To fill in these props
- public AbstractBaseClass(int sides, int length)
- {
- Sides = sides;
- Length = length;
- }
- //Calculate Perimeter. Number of sides * Length of each side
- public int CalcPerimeter()
- {
- return Sides * Length;
- }
- public abstract int CalcArea();
- }
- }
در اینجا، در کلاس انتزاعی به جای حفظ متد مجازی، فقط متد انتزاعی را نگه داشتم و متد انتزاعی نمی تواند بدنه را در کلاس پایه داشته باشد. حال، اجازه دهید اجرای آن را در کلاس مشتق شده ببینیم.
- namespace Interface_Demo.Lib
- {
- public class SquareAbstract: AbstractBaseClass
- {
- public SquareAbstract(int sides, int length): base(sides, length)
- {}
- public override int CalcArea()
- {
- return Sides * Length;
- }
- }
- }
نسبتا ساده و تمیز. به طور مشابه، برنامه اصلی برای همان، اکنون به شکل زیر است:
- using Interface_Demo.Lib;
- namespace Interface_Demo.Console
- {
- class Program
- {
- static void Main(string[] args)
- {
- var square = new Square(4, 4);
- DisplayDimensions("Square", square);
- var squareAbstract = new SquareAbstract(4, 4);
- DisplayDimensions("Square with abstract Implementation", squareAbstract);
- System.Console.ReadLine();
- }
- //dynamic key will resolve an object at runtime. very useful keyword
- private static void DisplayDimensions(string objectType, dynamic square)
- {
- System.Console.WriteLine("Displaying Dimensions of " + objectType);
- System.Console.WriteLine("Number of Sides:- " + square.Sides);
- System.Console.WriteLine("Length of Each Side:- " + square.Length);
- System.Console.WriteLine("Area of " + objectType + " is " + square.CalcArea());
- System.Console.WriteLine("Perimeter of " + objectType + " is " + square.CalcPerimeter());
- System.Console.WriteLine("==============================================================");
- }
- }
- }
با تغییر بالا، وقتی همان را اجرا می کنم، خروجی زیر را تولید می کند:
به طور مشابه، ما می توانیم موارد مشابه را با استفاده از رابط پیاده سازی کنیم. در زیر رابط نمونه برای همان و پیاده سازی آن است.
- namespace Interface_Demo.Lib
- {
- public interface ICircle
- {
- int radius
- {
- get;
- set;
- }
- //Only declarations, no Implementation
- double CalcPerimeter();
- double CalcArea();
- }
- }
- namespace Interface_Demo.Lib
- {
- public interface ICircle
- {
- int radius
- {
- get;
- set;
- }
- //Only declarations, no Implementation
- double CalcPerimeter();
- double CalcArea();
- }
- }
- namespace Interface_Demo.Lib
- {
- public class CircleInterface: ICircle
- {
- public int radius
- {
- get;
- set;
- }
- int ICircle.radius
- {
- get
- {
- return radius;
- }
- set
- {
- radius = value;
- }
- }
- public CircleInterface(int rad)
- {
- radius = rad;
- }
- public double CalcPerimeter()
- {
- return (2 * 3.14 * radius);
- }
- public double CalcArea()
- {
- return (3.14 * radius * radius);
- }
- }
- }
اکنون، برنامه اصلی برای همان شکل زیر خواهد بود.
- using Interface_Demo.Lib;
- namespace Interface_Demo.Console
- {
- class Program
- {
- static void Main(string[] args)
- {
- var square = new Square(4, 4);
- DisplayDimensions("Square", square);
- var squareAbstract = new SquareAbstract(4, 4);
- DisplayDimensions("Square with abstract Implementation", squareAbstract);
- var circleInterface = new CircleInterface(5);
- DisplayCircle("Circle with Interface Implementation", circleInterface);
- System.Console.ReadLine();
- }
- private static void DisplayCircle(string objectType, CircleInterface circleInterface)
- {
- System.Console.WriteLine("Displaying Dimensions of " + objectType);
- System.Console.WriteLine("Circle with Radius:- " + circleInterface.radius);
- System.Console.WriteLine("Area of " + objectType + " is " + circleInterface.CalcArea());
- System.Console.WriteLine("Perimeter of " + objectType + " is " + circleInterface.CalcPerimeter());
- System.Console.WriteLine("==============================================================");
- }
- //dynamic key will resolve an object at runtime. very useful keyword
- private static void DisplayDimensions(string objectType, dynamic square)
- {
- System.Console.WriteLine("Displaying Dimensions of " + objectType);
- System.Console.WriteLine("Number of Sides:- " + square.Sides);
- System.Console.WriteLine("Length of Each Side:- " + square.Length);
- System.Console.WriteLine("Area of " + objectType + " is " + square.CalcArea());
- System.Console.WriteLine("Perimeter of " + objectType + " is " + square.CalcPerimeter());
- System.Console.WriteLine("==============================================================");
- }
- }
- }
با اعمال تغییر فوق، خروجی زیر را تولید می کند:
بنابراین در این بخش هر سه را در عمل دیده ایم. حال، اجازه دهید چند نکته مهم را پیرامون این سه مورد بحث کنیم.
- کلاس Plain :
صادقانه بگویم، نقطه ضعف کلاس ساده یا کلاس ساده این است که پیاده سازی متدهای مجازی در کلاس مشتق شده را اعمال نمی کند. بنابراین، در زمان کامپایل هیچ خطایی ایجاد نمی کند، اما اگر تصادفاً همان متد را در برنامه اصلی فراخوانی کنید، در زمان اجرا استثنا پرتاب می کند.
- کلاس Abstract :
اجرای متد انتزاعی را در کلاس مشتق شده مجبور می کند، در غیر این صورت خطای زمان کامپایل را دریافت خواهیم کرد که بدیهی است که خوب است. با این حال، کلاسهای Abstract میتوانند شامل متدهای مشخص با پیادهسازی نیز باشند. در حال حاضر، در سی شارپ، یک کلاس می تواند تنها از یک کلاس به ارث برده شود، زیرا c# از وراثت چندگانه پشتیبانی نمی کند. اعضای کلاسهای انتزاعی میتوانند به اصلاحکنندههای دسترسی مانند عمومی، خصوصی، محافظتشده و غیره دسترسی داشته باشند. همچنین، کلاسهای انتزاعی میتوانند حاوی هر چیزی مانند رویدادها، فیلدها، ویژگیها، سازندهها، تخریبکنندهها، روشها، فهرستکنندهها باشند.
- رابط ها :
همچنین بررسی زمان کامپایل را اعمال می کند. شما باید تمام روش ها را از قبل پیاده سازی کنید. رابط نمی تواند هیچ پیاده سازی در داخل داشته باشد. فقط می تواند اعلامیه داشته باشد. همچنین یک کلاس می تواند چندین رابط را پیاده سازی کند. رابط ها به طور پیش فرض عمومی هستند. از این رو، اگر بخواهیم هر تغییر دهنده دسترسی را به هر عضو رابط اضافه کنیم، خطای زمان کامپایل را دریافت خواهیم کرد. اما، اینترفیس ها می توانند متدها، رویدادها، ایندکسرها یا ویژگی ها داشته باشند.
امیدوارم این بحث کوچک را دوست داشته باشید. ممنون که به من ملحق شدید.