PDA

View Full Version : شی گرایی (قسمت دوم )



zkazemi
جمعه 16 مرداد 1388, 18:14 عصر
کنترل دستيابي به کلاس:
جاي شگفتي است که ما هنوز استفاده کاربردي از کلاس circle نديده‌ايم. وقتي شما متدها و داده‌هاي خود را داخل يک کلاس کپسوله‌سازي مي‌نماييد مرزي بين کلاس و دنياي بيرون تعريف مي‌شود.
فيلدها (مثل Radius) و متدهاي (مثل Area) تعريف شده در کلاس فقط براي بقيه متدهاي داخل کلاس قابل رويت هستند.
به بيان ديگر, اگرچه شما يک شيء Circle در برنامه خود ايجاد نموده‌ايد هنوز شما نمي‌توانيد به فيلد Radius و يا متد Area کلاس دسترسي داشته باشيد که به همين علت است که تا کنون از اين کلاس استفاده نشده است. با اين حال شما مي‌توانيد با اصلاح فيلد و يا متد داخل کلاس با کلمات کليدي Public و يا private دسترسي بيروني به کلاس مدنظر را مديريت نماييد:
§ متد يا فيلدي که بصورت pravite تعريف شده باشد فقط از داخل کلاس قابل دسترسي خواهد بود. براي تعريف يک فيلد يا متد بصورت private کافي است قبل از تعريف متد يا فيلد کلمه کليدي private را بياوريم. گرچه بصورت پيش فرض همه متدها و فيلدها بصورت private تعريف مي‌شود ولي جهت جلوگيري از سردرگمي بهتر است بصورت صريح کلمه کليدي private را بياوريم.
§ متد يا فيلدي که بصورت public تعريف شده باشد در داخل و خارج کلاس قابل دسترسي خواهد بود براي تعريف يک متد يا فيلد بصورت public از کلمه کليدي public قبل از تعريف استفاده مي‌کنيم.
بار ديگر کلاس Circle را مي‌نويسيم اما اين بار متد Area را بصورت public و متد Radius را بصورت private تعريف مي‌کنيم:



class Cicle
{
public double Area ()
{
return 3.14592 * Radius * Radius;
}
private double Radius;
}دقت نماييد که radius بصورت private تعريف شده و خارج از کلاس قابل دسترسي نيست با اين حال مي‌توان از radius داخل کلاس Circle استفاده نمود. در اين روش چون متد Area داخل کلاس تعريف شده است مي‌تواند از فيلد radius استفاده نمايد. با اين حال هنوز براي مقداردهي فيلد radius دچار مشکل هستيم. براي رفع اين مشکل از Constructor استفاده مي‌کنيم.
نکته:
به صورت پيش‌فرض بسته به نوع داده آنها فيلدهاي داخل کلاس با مقادير 0, false و يا null مقداردهي مي‌شوند. با اين حال عادت خوبي است که مقدار دهي متغيرها به صورت صريح انجام شود.
نکته مهم:
استفاده از دو کلاس با نام يکسان و متفاوت در صف کوچک و بزرگ کار صحيحي نيست چون اگر اين کار را انجام دهيم بعلت عدم تطابق و هماهنگي با CLS, اين کلاسها در زبانهايي نظير Visual Basic که حساس به حروف کوچک و بزرگ نيستند کار نخواهد کرد.

کار با Constructor
وقتي شما براي ساخت يک شيء (Object) از کلمه کليدي new استفاده مي‌کنيد زبان عمومي زمان اجرا (CLR) بايد براي ساخت شيء از تعريف کلاس استفاده نمايد. CLR بايد مقداري از حافظه Ram را براي کار شيء تصور کرده آنرا با فيلدهاي تعريف شده در کلاس پر نمايد آنگاه بوسيله Constructor عمل مقداردهي آنها را انجام دهد.
Constructor متد خاصي است که همنام کلاس بوده که مي‌تواند يک سري پارامتر ورودي دريافت کند اما هيچ مقدار خروجي (حتي void) نخواهد داشت.
هر کلاس بايد يک Constructor داشته باشد, اگر شما براي کلاس خود Constructor ننويسيد, کامپايلر يک Constructor پيش فرض براي شما توليد خواهد نمود که البته حقيقتاً اين Constructor عملي انجام نخواهد داد.
شما مي‌توانيد براحتي Constructor خود را بنويسيد فقط کافي است يک متد public همنام کلاس خود ايجاد نماييد که هيچ مقداري را بعنوان خروجي برنگرداند.
مثال زير کلاس Circle را با Constructor پيش فرض نشان مي‌دهد که در آن مقدار فيلد radius برابر 0 قرار داده شده است.



class Circle
{
public Circle () // پيش فرض Constructor
{
radius = 0.0;
}
public double Area ()
{
return 3.141592 * radius * radius;
}
private double radius;
}نکته:
در زبان C#, Constructor پيش فرض به آن Constructor گفته مي‌شود که هيچ پارامتر ورودي دريافت نکند و اهميتي ندارد که آنرا شما ساخته باشيد و يا خود Compiler اين کار را کرده باشد. همچنين شما مي‌توانيد خودتان يک Constructor جديد ايجاد نماييد که در مبحث بعدي طريقه ايجاد آنرا فرا خواهيد گرفت.
توجه نماييد که Constructor بصورت public تعريف شود وگرنه Constructor بصورت private تعريف شده و نظير بقيه فيلدها و متدها خواهد بود. اگر Constructor بصورت private تعريف شود نمي‌توان خارج از کلاس به آن دسترسي پيدا کرد و اين باعث مي‌شود از ساختن نمونه‌اي از کلاس Circle توسط متدي که خارج کلاس Circle باشد جلوگيري‌کند و اين باعث مي‌شود به اين نتيجه برسيم که Private Constructor يک متد بي‌ارزش و غير قابل استفاده خواهد بود گرچه اين متدها هم استفاده خاصي دارند که از حوصله اين مبحث خارج است.
حالا وقت آن است که از کلاس Circle استفاده کرده و متد Area آنرا اجرا نماييد. به استفاده از علامت نقطه (".") جهت صدا کردن متد Area از شيء Circle دقت نماييد:



circle C;
C= new Circle ();
double areaofcircle = c.Area ();

حالتهاي مختلف Constructor
تا کنون شما مي‌توانيد يک متغير از نوع Circle تعريف کرده و نمونه جديدي از شيء circle ايجاد نماييد و سپس متد Area مربوط به آنرا فراخواني نمايد. اما هنوز يک مشکل وجود دارد و آن اين است که متد Area مساحت کليه دايره‌ها را صفر برخواهد گرداند چون Constructor پيش فرض مقدار radius را صفر قرار داده و همان خواهد ماند, چون فيلد radius بصورت private تعريف شده و راهي براي تغيير مجدد آن وجود ندارد.
يک راه براي حل اين مشکل درک اين مطلب است که Constructor هم متدي مثل بقيه متدهاست که مي‌تواند داراي overloadهاي مختلف باشد. همانطور که نسخه‌هاي مختلف متد Console.WriteLine وجود دارد و هر کدام پارامترهاي مختلفي را بعنوان ورودي دريافت مي‌کنند شما هم مي‌توانيد نسخه‌هاي مختلف Constructor را استفاده نماييد.



class circle
{
public circle () // پيش فرض Constructor
{
radius = 00;
}
public circle (double initialRadius) // overloaded Constructor
{
radius = initialRadius;
}
public double Area ()
{
return 3.141593 * radius * radius;
}
private double radius;
}


نکته:
ترتيب نوشتن متدهاي Constructor اهميت ندارد و هر طور که شما در نوشتن راحت‌تر هستيد همان ترتيب را مراعات کنيد.
مطلب مهم ديگري که بايد به آن توجه کنيد آن است که اگر شما خودتان يک Constructor تعريف نماييد کامپايلر Constructor پيش فرض را توليد نخواهد نمود لذا اگر در برنامه نياز داريد که Constructor پيش فرض را هم داشته باشيد بايد خودتان به صورت دستي آنرا بنويسيد.