مفاهیم ، مبانی و اصول شی گرایی (OOP) قسمت سوم
مفاهیم ، مبانی و اصول شی گرایی (OOP) قسمت سوم
در قسمت قبل با Constructor ها و Overloading متد ها آشنا شدیم . در این بخش قصد دارم به آموزش ساخت خواص یا Property بپردازم .
خصیصه ها یا خواص کاربرد زیادی در برنامه نویسی شی گرا دارند و جایگزین مناسبی برای بسیاری از متغیر های عمومی می باشند بنابراین فهم اینکه چرا به جای یک متغیر باید از Property استفاده کنیم بسیار اهمیت دارد .
در قسمت قبل یک کلاس ساختیم که در نهایتا به شکل زیر درآمد :
Imports Microsoft.VisualBasic Public Class Human Public Age As Integer = 0 Public Height As Integer = 0 Public Sub New() End Sub Public Sub New(ByVal InputHeight As Integer) Height = InputHeight End Sub Public Sub New(ByVal InputHeight As Integer, ByVal InputAge As Integer) Age = InputHeight End Sub Public Sub Grow() Age = Age + 1 Height = Height + 10 End Sub Public Sub Grow(ByVal iHeight As Integer, ByVal iAge As Integer) Age = Age + iHeight Height = Height + iAge End Sub Public Function Talk(ByVal Words As String) Return “He said : ” + Words End Function End Class |
این کلاس شامل دو متد به نام های Talk و Grow می باشد . البته متد Grow دارای دو Overload بود .
همچنین سه Overload برای Costructor این کلاس در نظر گرفتیم .
کلاس ما دو متغیر به نام های Height و Age داشت که به ترتیب قد و سن را در خود ذخیره می کرد . چون این دو متغیر از نوع Public هستند از خارج کلاس قابل دسترسی هستند و استفاده کننده از کلاس قادر است مقادیر آن ها را تغییر دهد ، خوب سوال اینجاست که اشکال این کار چیست ؟ از خارج از کلاس مقدار متغیر تغییر یابد !
پاسخ واضح است چون متغیر ها قابل کنترل نیستند نمیتوان بر روی مقادیر ارسالی به آنها کنترلی داشت .
به عنوان مثال فرض کنید شی Ali یک نمونه از کلاس Human است ، بنده مقدار متغیر Age یا سن Ali را برابر ۲۰۰۰ تعیین می کنم :
Dim Ali As New Human Ali.Age = 2000 |
و به همین راحتی سن Ali به ۲۰۰۰ سال رسید ! ولی این منطقی نیست چون هیچ انسانی نمی تواند ۲۰۰۰ سال عمر کند ( البته به استثنای حضرت نوح ) .
پس بنابراین ما نباید اجازه بدهیم که به متغیر های به این مهمی به این شکل مقدار دهی شود .
خوب راه حل چیست ؟ در نظر اول قرار دادن یک شرط ساده ترین راه ممکن است ولی شرط را در کجا قرار دهیم ؟ آیا میتوان داخل یک متغیر شرط قرار داد ؟
متاسفانه خیر !!
راه دومی که به ذهن می رسد Private کردن متغیر هاست تا از ارسال مقادیر به آنها جلوگیری شود ، ولی ما میخواهیم مقادیر این متغیر ها را دریافت و چاپ کنیم و Private کردن آنها با دسترسی به مقادیر آنها متناقض است .
برای همین Property ها به وجود آمدند ، Property ها دقیقا کار ارسال مقادیر به متغیر ها و دریافت آنها را انجام میدهند با این تفاوت که میتوان مقادیر را کنترل کرد .
بنابراین مشکل فوق به این شکل حل میشود که ابتدا متغیر Age و Height را Private کرده و سپس دو Property به همین نام ها یعنی Age و Height ایجاد می کنیم ، برای اینکه این نام ها باهم تضادی نداشته باشند نام متغیر ها را یک تغییر کوچک می دهیم تا با نام Property ها متفاوت شوند مثلا یک _ به اول نام متغیر ها اضافه میکنیم یعنی Age_ و Height_ متغیر های جدید ما هستند .
Private _Age As Integer = 0 Private _Height As Integer = 0 |
یک خصیصه یا property به شکل زیر تعریف می شود :
Public Property Age() As Integer Get End Get Set(ByVal value As Integer) End Set End Property |
خصیصه ها به اصطلاح دارای دو ابزار یا Accessor هستند : Get و Set .
ابزار Get وظیفه خارج کردن مقادیر از خصیصه را داشته و ابزار Set وظیفه ورود مقادیر . مقادیر خروجی توسط واژه Return خارج شده و مقادیر ورودی توسط متغیر Value که در کد فوق ملاحظه می کنید وارد می شوند .
در حقیقت دو عملی که بر روی متغیر انجام میشد(ارسال و دریافت مقادیر) در خصیصه ها جدا شده و هر کدام قابل کنترل هستند . همانند دو متد که وظیفه ارسال و دریافت مقادیر و کنترل آن ها را بر عهده دارند .
اکنون خصیصه Age را به صورت زیر کامل می نماییم :
Public Property Age() As Integer Get Return _Age End Get Set(ByVal value As Integer) _Age = value End Set End Property |
در این خصیصه همان مقدار ورودی یعنی value به متغیر Age_ ما ارسال و مقدار متغیر Age_ در بخش Get خارج می گردد.
این کد دقیقا کار متغیر Age را انجام می دهد (هنوز کنترلی بر روی مقادیر انجام نشده است) .
حال سعی می کنیم مقادیر ورودی را کنترل نماییم :
Public Property Age() As Integer Get Return _Age End Get Set(ByVal value As Integer) If 0 < value < 100 Then _Age = value End If End Set End Property |
همانطور که ملاحظه می کنید با یک If ساده از ارسال مقادیر خارج از بازه ۰ تا ۱۰۰ جلوگیری کردیم .
Property ها می توانند ReadOnly (فقط خواندنی) و یا WriteOnly (فقط نوشتنی) باشند . برای مثال یک متغیر Private به نام رنگ چشم (EyeColor_) به کلاس اضافه کنید :
Private _EyeColor As String |
و یک Property به نام EyeColor برای کنترل مقادیر این متغیر می سازیم . اما باید دقت کنیم که رنگ چشم یک خاصیت فقط خواندنی است زیرا رنگ چشم انسان ها تغییر نمی کند بنابراین خاصیت رنگ چشم را به صورت زیر تعریف می کنیم :
Public ReadOnly Property EyeColor() As String Get Return _EyeColor End Get End Property |
واژه ReadOnly باعث می شود که ابزار Set غیر فعال شده و خصیصه فقط خواندی باشد .
حال سوالی که ممکن است مطرح شود این است که پس مقدار رنگ چشم کجا تعیین می شود ؟
پاسخ : همانطور که در دنیای خارج رنگ چشم یک نوازد در هنگام بدو تولد مشخص می شود در کلاس Human ما هم در هنگام ایجاد باید رنگ چشم تعیین گردد یعنی در Constructor یک ورودی برای رنگ چشم در نظر گرفته و مقدار ورودی را به متغیر EyeColor_ ارسال می نماییم .
Public Sub New(ByVal EyeColor As String) _EyeColor = EyeColor End Sub |
در خارج از کلاس :
Dim Ali As New Human(“Brown”) Response.Write(Ali.EyeColor) |
در صورتی که بخواهیم به خصیصه EyeColor مقدار دهی کنیم دات نت از این کار جلوگیری کرده و خطایی مبنی بر ReadOnly بودن خاصیت داده می شود .
برخی از خواص نیز WriteOnly هستند که به صورت زیر تعریف می گردند :
Public WriteOnly Property MyWriteOnlyProperty() Set(ByVal value) ‘ Some Code…. End Set End Property |
property ها کاربر فراوانی در شی گرایی دارند و معمولا به جای استفاده از متغیر های Public از متغیر های Private به همراه یک Property از نوع Public استفاده می شود .
آخرین دیدگاهها