در این مقاله از سری مقالات آموزشی پی استور به بررسی کلاس Abstract در سی شارپ و مقایسه انتزاع «Abstraction» و کپسولهسازی «Encapsulation» پرداخته و مزایای آنها در ایجاد نرمافزارهای بهینه و ایمن را بررسی خواهیم کرد.
در دنیای برنامهنویسی شیگرا، مفاهیم انتزاع و کپسولهسازی به عنوان دو اصل اساسی در طراحی نرمافزار شناخته میشوند. این مفاهیم به توسعهدهندگان کمک میکنند تا سیستمهایی با کد تمیز، قابل نگهداری و ایمن ایجاد کنند. انتزاع، با پنهان کردن جزئیات پیچیده و نمایش تنها ویژگیهای ضروری، به کاهش پیچیدگی و افزایش فهم کاربر کمک میکند. کپسولهسازی نیز با محدود کردن دسترسی مستقیم به دادهها و فراهم آوردن متدهایی برای تعامل با آنها، از امنیت و انسجام سیستم پشتیبانی میکند.
مفهوم انتزاع شیگرایی
انتزاع دادهها، property است که در آن تنها جزئیات ضروری برای کاربر نمایش داده میشود و جزئیات یا پیادهسازیهای غیرضروری از کاربر پنهان میماند. به عبارت دیگر، انتزاع دادهها میتواند به عنوان فرایند شناسایی تنها ویژگیهای مورد نیاز یک شیء و نادیده گرفتن جزئیات غیر مرتبط تعریف شود. ویژگیها و رفتارهای یک شیء آن را از سایر اشیای مشابه متمایز میکند و همچنین در طبقهبندی یا گروهبندی اشیاء کمک میکند.
مثال: سناریوی واقعی برداشت پول از یک دستگاه خودپرداز (ATM) را در نظر بگیرید. کاربر فقط میداند که در دستگاه خودپرداز ابتدا کارت ATM را وارد میکند، سپس کد PIN کارت ATM را وارد کرده و سپس مقدار پولی که میخواهد برداشت کند را وارد میکند و در نهایت، پول خود را دریافت میکند. آنها از مکانیزم داخلی دستگاه خودپرداز یا پیادهسازی برداشت پول و غیره اطلاعی ندارند. کاربر فقط به طور ساده میداند که چگونه دستگاه خودپرداز را استفاده کند، این همان انتزاع است.
در زبان برنامه نویسی سی شارپ انتزاع با کمک کلاس Abstract و رابطها «Interface» به دست میآید.
کلاس Abstract در سی شارپ چیست ؟
کلاس Abstract در سی شارپ کلاسی است که نمیتوان مستقیماً از آن نمونهسازی کرد. کلاسهای انتزاعی زمانی استفاده میشوند که بخواهیم یک قالب مشترک برای گروهی از کلاسهای مرتبط تعریف کنیم، اما برخی از متدها یا ویژگیها را برای پیادهسازی در کلاسهای مشتقشده باقی بگذاریم.
- یک کلاس Abstract را نمیتوان مستقیماً نمونهسازی کرد. فقط میتوان از کلاسهای مشتقشده از آن شیء ایجاد کرد.
- متدهای انتزاعی در کلاسهای Abstract تعریف میشوند اما پیادهسازی ندارند، بنابراین کلاسهای مشتقشده باید آنها را پیادهسازی کنند.
- یک کلاس Abstract همچنین میتواند شامل ویژگیها «Properties» و فیلدهایی باشد که توسط کلاسهای مشتقشده قابلدسترسی هستند.
مثال ۱: تکه کد زیر یک نمونه ساده از انتزاع «Abstraction» و پلیمورفیسم «Polymorphism» در برنامهنویسی شیگرا با استفاده از زبان #C است. در این مثال، ما از یک کلاس Abstract برای تعریف ویژگیهای عمومی حیوانات استفاده کردهایم و سپس دو کلاس مشتق شده برای Cat و Dog پیادهسازی میکنیم.
// C# program to demonstrates the // working of abstract classses using System; public abstract class Animal { public abstract string Sound { get; } public virtual void Move() { Console.WriteLine("Moving..."); } } public class Cat : Animal { public override string Sound => "Meow"; public override void Move() { Console.WriteLine("Walking like a cat..."); } } public class Dog : Animal { public override string Sound => "Woof"; public override void Move() { Console.WriteLine("Running like a dog..."); } } class Program { static void Main(string[] args) { Animal[] animals = new Animal[] { new Cat(), new Dog() }; foreach (Animal animal in animals) { Console.WriteLine($"The {animal.GetType().Name} goes {animal.Sound}"); animal.Move(); } } }
خروجی
The Cat goes Meow Walking like a cat... The Dog goes Woof Running like a dog...
- در مثال بالا، کلاس Animal یک کلاس Abstract است که رفتارهای مشترک حیوانات (مانند حرکت) را تعریف میکند، ولی جزئیات دقیق (مانند صدای حیوانات و نحوه حرکت) به کلاسهای مشتق شده واگذار شده است.
- در این کد، از پلیمورفیسم استفاده شده است. به این معنی که شیء از نوع Animal میتواند به شیء از نوعهای مختلف (مانند Cat یا Dog) ارجاع داده شود و متدهای خاص هر کلاس مشتق را فراخوانی کند.
- متد ()Move در کلاس Animal با استفاده از کلمه کلیدی virtual مشخص شده است تا امکان بازنویسی آن در کلاسهای مشتق شده فراهم شود. ویژگی Sound نیز با استفاده از override در کلاسهای مشتق پیادهسازی شده است.
تعریف کلاس Abstract در سی شارپ
abstract class PStore{} // class ‘PStore’ is abstract
نکات مهم کلاس Abstract در سی شارپ
- معمولاً کلاسهای Abstract هنگام استفاده از ارثبری به کار میروند.
- برای پیادهسازی متد انتزاعی در کلاس فرزند، باید از کلمه کلیدی override استفاده شود.
- کلاس Abstract در سی شارپ نمیتواند توسط structها به ارث برده شود.
- میتواند شامل سازنده «constructor» یا نابودگر «destructor» باشد.
- میتواند متدهایی با پیادهسازی غیرانتزاعی داشته باشد.
- از چندگانگی ارثبری «multiple inheritance» پشتیبانی نمیکند.
- نمیتواند static باشد.
مثال ۲: تکه کد زیر نشاندهندهی مفهوم انتزاع در سی شارپ است و از کلاس abstract برای تعریف رفتارهایی استفاده میکند که در کلاسهای مشتق باید پیادهسازی شوند. همچنین، از مفهوم پلیمورفیسم «Polymorphism» برای فراخوانی متدهای بازنویسیشده در کلاسهای مشتق شده استفاده میشود.
// Abstract class working using System; // Abstract class BaseClass public abstract class BaseClass { // Abstract method 'Display()' public abstract void Display(); } // Class Child1 inherits from BaseClass public class Child1 : BaseClass { // Implement abstract method Display() with override public override void Display() { Console.WriteLine("class Child1"); } } // Class Child2 inherits from BaseClass public class Child2 : BaseClass { // Implement abstract method 'Display()' with override public override void Display() { Console.WriteLine("class Child2"); } } public class PStore { public static void Main() { // Declare variable b of type BaseClass BaseClass b; // Instantiate Child1 b = new Child1(); // Call Display() of class Child1 b.Display(); // Instantiate Child2 b = new Child2(); // Call Display() of class Child2 b.Display(); } }
خروجی
class Child1 class Child2
- در مثال بالا کلاس BaseClass یک کلاس انتزاعی است که متد ()Display را به صورت انتزاعی تعریف میکند. کلاسهای Child1 و Child2 مسئول پیادهسازی این متد هستند.
- متغیر b از نوع BaseClass است، اما میتواند به شیء از هر کلاسی که از BaseClass ارثبری میکند (در اینجا Child1 و Child2) ارجاع دهد. این نشاندهندهی استفاده از پلیمورفیسم است، زیرا در زمان اجرا مشخص میشود که متد ()Display کدام کلاس فراخوانی شود.
- در کلاسهای Child1 و Child2, متد ()Display با استفاده از کلمه کلیدی override پیادهسازی شده است تا رفتار خاص هر کلاس مشخص شود.
مثال ۳: تکه کد زیر نشاندهندهی استفاده از متد غیر انتزاعی «Non-abstract method» در یک کلاس Abstract در سی شارپ و همچنین نحوه پیادهسازی متدهای انتزاعی «Abstract methods» در کلاسهای مشتق است. در این کد از دو متد استفاده شده است: یکی که پیادهسازی آن در کلاس انتزاعی است و دیگری که در کلاس مشتق شده بازنویسی (override) شده است.
// C# program to demonstrates the working of // the non-abstract method in the // abstract class using System; abstract class AbstractClass { // Non abstract method public int AddTwoNumbers(int Num1, int Num2) { return Num1 + Num2; } // An abstract method which // overridden in the derived class public abstract int MultiplyTwoNumbers(int Num1, int Num2); } // Child Class of AbstractClass class Derived : AbstractClass { // implementing the abstract // method 'MultiplyTwoNumbers' // using override keyword, public override int MultiplyTwoNumbers(int Num1, int Num2) { return Num1 * Num2; } } // Driver Class class PStore { // Main Method public static void Main() { // Instance of the derived class Derived d = new Derived(); Console.WriteLine("Addition: {0}\nMultiplication: {1}", d.AddTwoNumbers(4, 6), d.MultiplyTwoNumbers(6, 4)); } }
خروجی
Addition: 10 Multiplication: 24
- در مثال بالا در کلاس AbstractClass, متد AddTwoNumbers یک متد غیر انتزاعی است که در خود کلاس پیادهسازی شده و نیازی به پیادهسازی مجدد در کلاسهای مشتق ندارد.
- متد MultiplyTwoNumbers در کلاس AbstractClass به صورت انتزاعی تعریف شده است و باید در هر کلاس مشتق شده پیادهسازی شود.
- در کلاس Derived, متد MultiplyTwoNumbers با استفاده از کلمه کلیدی override پیادهسازی شده است که رفتار خاص آن را مشخص میکند.
- کد بالا نشان میدهد که چگونه از کلاسهای انتزاعی برای تعریف رفتارهای عمومی (مانند جمع کردن) و استفاده از کلاسهای مشتق برای پیادهسازی رفتارهای خاص (مانند ضرب کردن) استفاده میشود.
توجه: یک متد انتزاعی، متدی است که در یک کلاس انتزاعی تعریف میشود اما بدنهای ندارد. هر کلاس غیرانتزاعی که از کلاس انتزاعی ارثبری میکند، باید پیادهسازی این متد را ارائه دهد.
مثال ۴: تکه کد زیر نشاندهندهی استفاده از کلاس Abstract در سی شارپ و متد انتزاعی (Abstract method) برای محاسبه مساحت یک مربع است. در اینجا از یک کلاس انتزاعی برای تعریف یک متد انتزاعی به نام Area استفاده شده که در کلاسهای مشتق باید پیادهسازی شود. سپس در کلاس مشتق شده (Square), این متد برای محاسبه مساحت مربع بازنویسی شده است.
// C# program to calculate the area // of a Square using abstract class // and abstract method using System; // declare class AreaClass // as abstract abstract class AreaClass { // declare method // Area as abstract abstract public int Area(); } // class AreaClass inherit // in child class Square class Square : AreaClass { int side = 0; // constructor public Square(int n) { side = n; } // the abstract method // Area is overridden here public override int Area() { return side * side; } } class PStore { // Main Method public static void Main() { Square s = new Square(6); Console.WriteLine("Area = " + s.Area()); } }
خروجی
Area = 36
- در مثال بالا کلاس AreaClass یک کلاس انتزاعی است که متد ()Area را به صورت انتزاعی تعریف میکند، بنابراین هیچ پیادهسازی ندارد و باید در کلاسهای مشتق پیادهسازی شود.
- متد Area() یک متد انتزاعی است که در کلاس Square پیادهسازی شده است تا مساحت مربع را محاسبه کند.
- در کلاس Square, متد ()Area با استفاده از کلمه کلیدی override بازنویسی شده است. این نشان میدهد که متد ()Area در این کلاس به طور خاص برای مربع پیادهسازی شده است.
- استفاده از abstract برای متدها و کلاسها، و همچنین استفاده از override برای بازنویسی متدهای انتزاعی، مفاهیم مهم در برنامهنویسی شیگرا و انتزاع هستند.
مثال ۵: تکه کد زیر نشاندهندهی نحوه استفاده از کلاسهای انتزاعی «Abstract classes» و ویژگیها «Properties» در زبان C# است که به همراه دسترسپذیرها «Accessors» مانند get و set پیادهسازی شدهاند.
// C# program to demonstrates the working // of abstract class with the // get and set accessors using System; abstract class absClass { protected int n; public abstract int n1 { get; set; } } class absDerived : absClass { // Implementing abstract properties public override int n1 { get { return n; } set { n = value; } } } // Driver Class class PStore { // Main Method public static void Main() { absDerived d = new absDerived(); d.n1 = 5; Console.WriteLine(d.n1); } }
خروجی
۵
- در مثال بالا در کلاس absClass, ویژگی n1 به صورت انتزاعی تعریف شده است و در کلاسهای مشتق باید پیادهسازی شود.
- ویژگی n1 از دسترسپذیرهای get و set استفاده میکند تا امکان دسترسی به مقدار متغیر n در کلاس مشتق شده فراهم شود.
- در کلاس absDerived, ویژگی n1 به طور خاص پیادهسازی شده است و در اینجا از get و set برای مدیریت مقدار n استفاده میشود.
- کد بالا نشان میدهد که چگونه میتوان از کلاسهای انتزاعی برای تعریف ویژگیها و رفتارهایی استفاده کرد که باید در کلاسهای مشتق پیادهسازی شوند.
استفاده از رابط یا Interface در سی شارپ
رابط با استفاده از کلمه کلیدی interface اعلام میشود. ما میتوانیم متدهای انتزاعی داخل رابط ایجاد کنیم که مشابه با کلاسهای انتزاعی هستند و عملکرد آنها را در کلاس مشتق شده اعلام کنیم. از کلاس مشتق شده میتوانیم به آن propertyها دسترسی پیدا کنیم، با ایجاد نمونهای از شیء کلاس مشتق شده.
مثال
using System; // interface public interface Student { //abstract method void FavSub(); } // Subclass for functionality public class Program : Student { public void FavSub() { Console.WriteLine("My favorite subject is C#"); } } public class PStore { public static void Main() { Student obj = new Program(); obj.FavSub(); } }
خروجی
My favorite subject is C#
تفاوت کپسوله سازی و انتزاع در سی شارپ
انتزاع و کپسولهسازی از ویژگیهای مهم برنامهنویسی شیگرا (OOP) هستند. عملکرد آنها مشابه است، اما تفاوتهای اندکی دارند که در زیر نشان داده شده است:
ویژگیها | انتزاع | کپسولهسازی |
تعریف | پنهان کردن اجرا و افشای جزئیات ضروری. | داده ها و اطلاعات را در یک واحد محصور کنید و دسترسی را از طریق دسترسی ها فراهم کنید. |
پیادهسازی | با استفاده از کلاس های انتزاعی و رابط و ویژگی ها پیاده سازی می کند. | پیاده سازی با استفاده از اصلاح کننده های دسترسی در سی شارپ |
هدف | برای پنهان کردن عملکرد پیچیده و نشان دادن رابط کاربر پسند استفاده می شود. | تامین امنیت و جلوگیری از دسترسی غیرمجاز به داده ها. |
مثال | یک کلاس خودرو دارای ویژگی های مختلفی مانند drive()، break () و ()gear است و می توانیم بدون اطلاع از پیاده سازی از آن استفاده کنیم. | دسترسی های ()get و ()set را برای ارائه کنترل های دسترسی روی داده ها دریافت کنید. |
انتزاع: تمرکز بر پنهان کردن جزئیات غیرضروری و نمایش تنها ویژگیهای مهم و ضروری است. در انتزاع، فقط “چه چیزی” انجام میشود، اما پیادهسازی دقیق آن پنهان میماند.
کپسولهسازی: به معنای پنهان کردن دادهها و ارائه روشهایی برای دسترسی و تغییر آنها است. در کپسولهسازی، دادهها از دسترسی مستقیم خارج شده و از طریق متدها یا ویژگیها به آنها دسترسی پیدا میشود.
به طور کلی، انتزاع بیشتر مربوط به “چه چیزی” باید انجام شود، در حالی که کپسولهسازی به “چگونه” انجام دادن آن متمرکز است.
مزایای کلاس Abstract در سی شارپ
- کپسولهسازی: کلاس Abstract در سی شارپ به ما امکان میدهند یک مجموعه مشترک از رفتارها یا ویژگیهایی را تعریف کنیم که کلاسهای مشتقشده باید داشته باشند، بدون اینکه جزئیات پیادهسازی آنها را برای دنیای خارج فاش کنیم. این کار به ایجاد کدی انعطافپذیرتر و قابلنگهداریتر کمک میکند.
- استفاده مجدد از کد: کلاس Abstract در سی شارپ میتوانند بهعنوان کلاس پایه برای چندین کلاس مشتقشده استفاده شوند، که این امر باعث کاهش تکرار کد و بهبود استفاده مجدد از آن میشود.
- چندریختی «Polymorphism»: کلاس Abstract در سی شارپ میتوانند چندریختی را امکانپذیر کنند، که به ما اجازه میدهد کدی بنویسیم که با اشیای کلاسهای مشتقشده مختلف کار کند، به شرطی که همه آنها از یک کلاس پایه انتزاعی مشترک ارثبری کنند.
معایب کلاس Abstract در سی شارپ
- وابستگی زیاد «Tight Coupling»: کلاسهای انتزاعی میتوانند وابستگی زیادی بین کلاس پایه و کلاسهای مشتقشده ایجاد کنند، که این امر میتواند تغییر کلاس پایه را بدون تأثیر بر کلاسهای مشتقشده دشوار کند.
- محدودیت در ارثبری: در سی شارپ، یک کلاس فقط میتواند از یک کلاس پایه ارثبری کند، بنابراین اگر از یک کلاس انتزاعی بهعنوان کلاس پایه استفاده کنیم، قابلیت ارثبری از سایر کلاسها را محدود میکنیم.
- مشکل در تستنویسی: از آنجا که کلاسهای انتزاعی را نمیتوان مستقیماً نمونهسازی کرد، تست آنها نسبت به کلاسهای معمولی دشوارتر است. برای تست یک کلاس مشتقشده، ممکن است نیاز به ایجاد یک Mock یا Stub از کلاس پایه انتزاعی داشته باشیم.
نتیجهگیری
کلاسهای انتزاعی ابزار قدرتمندی در برنامهنویسی شیءگرا هستند که به ما این امکان را میدهند تا ساختارهای کد خود را بهطور مؤثری سازماندهی کنیم و از قابلیتهایی مانند کپسولهسازی، استفاده مجدد از کد و چندریختی بهرهمند شویم. استفاده از کلاس Abstract در سی شارپ میتواند منجر به نوشتن کدی تمیزتر و قابلنگهداریتر شود، به ویژه زمانی که در پروژههای بزرگ نیاز به استانداردسازی و سازماندهی کدهای مختلف داریم. با این حال، مانند هر ابزار دیگری، کلاس Abstract نیز معایب خاص خود را دارد، از جمله وابستگی زیاد و محدودیت در ارثبری که ممکن است در برخی موارد چالشبرانگیز باشد.
در نهایت، انتزاع و کپسولهسازی دو ویژگی کلیدی در برنامهنویسی شیگرا هستند که به طرز قابل توجهی در بهبود ساختار، خوانایی و امنیت نرمافزارها تأثیرگذارند. انتزاع با کاهش پیچیدگی و پنهان کردن جزئیات غیرضروری، تجربه کاربری سادهتر و کد قابل نگهداریتری فراهم میآورد. از طرف دیگر، کپسولهسازی با محافظت از دادهها و جلوگیری از دسترسیهای غیرمجاز به آنها، امنیت و یکپارچگی برنامهها را افزایش میدهد. استفاده مؤثر از این دو مفهوم، به برنامهنویسان کمک میکند تا نرمافزارهایی امن، بهینه و قابل توسعه ایجاد کنند که به راحتی قابل تغییر و ارتقاء باشند.