دسته بندي ها

جستجو

لينک هاي روزانه

جعبه پیام




امکانات


آرشيو

خبرنامه

آمار

آنلاین : 1
بازدید امروز : 14
بازدید دیروز : 11
بازدید هفته گذشته : 48
بازدید ماه گذشته : 150
بازدید سال گذشته : 2203
کل بازدید : 10205

لينک دوستان

کنترل دسترسي به اعضاي کلاس

Encapsulation در سي‌شارپ بدين معناست که اطلاعات يک کلاس در برابر دسترسي‌هاي غيرمجاز و خراب‌کاري محفوظ نگه داشته شود. کلاس که امکان encapsulation را به شما مي‌دهد، دو مزيت عمده ديگر نيز به همراه دارد. اول اينکه داده‌ها را به کدهاي درون کلاس متصل مي‌کند. دوم اينکه دسترسي به اعضاي کلاس را کنترل مي‌کند. تا اينجا شما با دو نوع از اعضاي کلاس آشنا شده‌ايد که يکي public بود و ديگري private.

زنگ سي‌شارپ - قسمت بيستم و چهارم

عضوي که public است مي‌تواند آزادانه در خارج از کلاس خودش نيز قابل دسترسي باشد. اعضاي private فقط درون همان کلاس قابل دسترسي هستند و البته از طريق يک متد public مي‌توانند قابل دسترسي و کنترل باشند.


محدود کردن دسترسي به اعضاي يک کلاس يکي از طراحی وب سایت بخش‌هاي اساسي برنامه‌نويسي شي‌گرا است چراکه از استفاده‌ي نادرست يک شيء جلوگيري مي‌کند. کنترل دسترسي از طريق access modifier ها انجام مي‌شود که public، private، protected و internal هستند. فعلاً به public و private مي‌پردازيم و protected و internal در جاي خود توضيح داده مي‌شوند. استفاده به‌موقع و به‌جا از public و private يکي از نکات مهم و کليدي برنامه‌نويسي شي‌گرا است. در زير به چند نکته در اين مورد اشاره شده:

آن دسته از اعضاي کلاس که فقط در همان کلاس استفاده مي‌شوند بايد private باشند.
داده‌هايي که بايد بين يک محدوده خاص باشند نيز بايد private باشند و دسترسي به آن‌ها از طريق يک متد public که بازه‌ي اعداد را بررسي مي‌کند، کنترل شود.
اگر تغيير دادن يکي از اعضا موجب شود که تاثير اين تغيير از آن عضو فراتر رود (و بر قسمت‌هاي ديگر شيء تاثير گذارد)، آن عضو بايد private باشد و دسترسي به آن بايد کنترل شود.
آن دسته از اعضا که درصورت استفاده نادرست موجب مي‌شوند که شيء آسيب ببينيد و آن‌طور که بايد رفتار نکند، بايد private باشند و دسترسي به آن‌ها از طريق متدهاي public انجام شود تا از استفاده‌ي نادرست آن‌ها جلوگيري شود.
متدهايي که مقداري را به اعضاي private اختصاص مي‌دهند يا مقدار آن‌ها را مي‌خوانند، بايد public باشند.
اگر هيچ دليلي براي private کردن متغيرهاي کلاس نيافتيد، مي‌توانيد آن‌ها را public در نظر بگيريد.
البته نکات ظريف ديگري نيز وجود دارندکه در بالا به آن‌ها شاره نکرديم اما در کل اگر همين قوانين را رعايت کنيد اشيايي که مي‌سازيد به‌راحتي خراب نمي‌شوند و مورد سوءاستفاده قرار نمي‌گيرند.

براي اين‌که درک بهتري از اين موارد داشته باشيد و بدانيد که چرا و چگونه از اين‌ها استفاده مي‌کنيم، مثالي از ساختمان داده‌ي stack مي‌تواند مفيد باشد. يکي از مثال‌هاي مفيد برنامه‌نويسي شي‌گرا کلاسي است که stack را پياده‌سازي و اجرا مي‌کند. همان‌طور که احتمالاً مي‌دانيد، stack ساختاري است براي ذخيره کردن اطلاعات که در آن اولين مقدار ذخيره شده، آخرين مقداري است که مورد استفاده قرار مي‌گيرد. اين‌طور تصور کنيد که تعدادي ظرف را روي ميزي (روي هم) قرار داده‌ايد. اولين ظرفي که روي ميز قرار داديد، آخرين ظرفي است که مي‌توانيد آن را برداريد يا برعکس، آخرين ظرفي که گذاشته‌ايد، اولين ظرفي است که مي‌توانيد آن را برداريد. به اين مکانيسم در اصطلاح Last-in, First-out مي‌گويند. کلاسي که ما براي اين منظور تعريف مي‌کنيم شامل محلي براي ذخيره‌سازي اطلاعات و متدهايي براي کنترل روي اين اطلاعات است بنابراين stack درواقع يک data engine است که اين اجبار را به‌وجود مي‌آورد تا عمليات Last-in, First-out اجرا شود. با اين تعاريف نياز است که يک‌سري از اعضاي کلاس private و يک‌سري ديگر public باشند تا بتوان مکانيسم Last-in, First-out را اجرا کرد.

يک stack دو عملکرد پايه‌اي را انجام مي‌دهد که عمل push و pop هستند. Push يک مقدار را به بالاي stack اضافه مي‌کند و pop يک مقدار را از بالاي stack حذف مي‌کند. کلاسي که تعريف خواهيم کرد، شامل يک آرايه‌ي private براي ذخيره سازي اطلاعات و دو متد public که عمليات pop و push را انجام مي‌دهند و Last-in, First-out را پياده مي‌کنند:
// A stack class for characters
class Stack
{
// These members are private
char[] stck; // holds the stack
int tos; // index of the top of the stack

// Construct an empty Stack given its size.
public Stack(int size)
{
stck = new char[size]; // allocate memory for stack
tos = 0;
}

// Push characters onto the stack
public void Push(char ch)
{
if (tos == stck.Length)
{
Console.WriteLine("Stack is full!");
return;
}
stck[tos] = ch;
tos++;
}

// Pop a character from the stack.
public char Pop()
{
if (tos == 0)
{
Console.WriteLine("Stack is empty!");
return (char)0;
}
tos--;
return stck[tos];
}

// Return true if the stack is full.
public bool IsFull()
{
return tos == stck.Length;
}

// Return true if the stack is empty.
public bool IsEmpty()
{
return tos == 0;
}

// Return total capacity of the stack.
public int Capacity() { return stck.Length; }

// Return number of objects currently on the stack.
public int GetNum() { return tos; }
}
بهتر است به اين کلاس دقيق‌تر نگاه کنيم. کلاس Stack با تعريف اين دو instance variables شروع مي‌شود:

1
2
3
// These members are private
char[] stck; // holds the stack
int tos; // index of the top of the stack
آرايه‌ي stck محلي براي ذخيره‌سازي اطلاعات در stack فراهم مي‌کند که اين آرايه کاراکتر را در خود نگه مي‌دارد. تخصيص آرايه توسط constructor انجام مي‌گيرد و متغير tos ايندکس (شماره) بالاترين خانه‌ي stack را در خود نگه مي‌دارد.

هر دو عضو tos و stck به‌صورت private هستند و اين باعث مي‌شود که مکانيسم Last-in, First-out اجرا شود. اگر دسترسي اين دو به‌صورت public تعريف شود آن‌گاه عناصر stack مي‌توانند خارج از ترتيب قابل دسترسي باشند. همچنين از آن‌جا که متغير tos ايندکس بالاترين عنصر stack را نگهداري مي‌کند بايد دسترسي به آن محدود شود تا توسط کدهاي خارج از کلاس در دسترس و قابل دستکاري و خراب‌کاري نباشد. البته دسترسي به tos و stck از طريق متدهاي public امکان‌پذير است.

در خط بعد constructor را مي‌بينيد:

// Construct an empty Stack given its size.
public Stack(int size)
{
stck = new char[size]; // allocate memory for stack
tos = 0;
}
توسط constructor اندازه دل‌خواه stack مشخص شده و آرايه مورد نظر ساخته مي‌شود. همچنين به متغير tos مقدار صفر اختصاص مي‌يابد. بنابراين مقدار صفر براي tos مشخص مي‌کند که stack خالي است.

متد ()Push که public تعريف شده، يک عنصر را به stack اضافه مي‌کند:


// Push characters onto the stack
public void Push(char ch)
{
if (tos == stck.Length)
{
Console.WriteLine("Stack is full!");
return;
}
stck[tos] = ch;
tos++;
}
عنصري که قرار است به stack افزوده شود از طريق پارامتر ch وارد stack مي‌شود. البته قبل از اين‌که عنصري به stack اضافه شود ابتدا بررسي مي‌شود که stack هنوز خانه‌ي خالي داشته باشد. اين‌کار با بررسي اين‌که tos از طول stck فراتر نرفته باشد انجام مي‌شود. سپس کاراکتر در ايندکسي که tos مشخص مي‌کند ذخيره مي‌شود و در نهايت tos يک واحد افزايش مي‌يابد. بنابراين tos هميشه ايندکس خانه‌ي بعدي stck را در خود نگه مي‌دارد.

براي پاک کردن يک عنصر از stack از متد ()Pop استفاده مي‌کنيم:

// Pop a character from the stack.
public char Pop()
{
if (tos == 0)
{
Console.WriteLine("Stack is empty!");
return (char)0;
}
tos--;
return stck[tos];
}
در اين‌جا مقدار tos بررسي مي‌شود، اگر برابر با
طراحی وب سایت
 صفر بود stack خالي است در غير اين‌صورت tos يک واحد کاهش مي‌يابد و عنصري که tos به آن اشاره مي‌کند return مي‌شود.

اگرچه ()Push و ()Pop تنها متدهايي هستند که براي اجراي يک stack مورد نياز است اما تعريف چند متد ديگر نيز مي‌تواند مفيد باشد. ما در اين کلاس ? متد بيشتر تعريف کرده‌ايم که ()IsFull()، IsEmpty()، Capacity و ()GetNum نام دارند و اطلاعاتي را از وضعيت stack به ما مي‌دهند:

// Return true if the stack is full.
public bool IsFull()
{
return tos == stck.Length;
}

// Return true if the stack is empty.
public bool IsEmpty()
{
return tos == 0;
}


// Now, pop from stk1 and push the element in stk2.
// This causes stk2 to hold the elements in reverse order.
Console.WriteLine("Now, pop chars from stk1 and push " +
"them onto stk2.");
while (!stk1.IsEmpty())
{
ch = stk1.Pop();
stk2.Push(ch);
}

Console.Write("Contents of stk2: ");
while (!stk2.IsEmpty())
{
ch = stk2.Pop();
Console.Write(ch);
}
Console.WriteLine("\n");

// Put 5 characters into stack.
Console.WriteLine("Put 5 characters on stk3.");
for (i = 0; i < 5; i++)
stk3.Push((char)('A' + i));

Console.WriteLine("Capacity of stk3: " + stk3.Capacity());
Console.WriteLine("Number of objects in stk3: " +
stk3.GetNum());
}
}
خروجي:



در مثال بعد قصد داريم برنامه دفترچه تلفن سابق را بيشتر شي‌گرا کنيم. در اين دفترچه تلفن يک کلاس براي مخاطب داريم و يک کلاس براي دفترچه تلفن. در کلاس مخاطب، متغيرهاي نام، آدرس و شماره تلفن قرار دارد. در کلاس دفترچه تلفن، متدهايي براي جستجو، افزودن مخاطب جديد و نمايش مخاطبان ذخيره شده وجود دارد:

1using System;
class MainClass
{
static void Main()
{
Phonebook myPhonebook = new Phonebook(5);
while (true)
{
Console.Clear();
Console.WriteLine("1. Add");
Console.WriteLine("2. Search By Name");
Console.WriteLine("3. Show all");
Console.WriteLine("4. Exit");
Console.WriteLine();
Console.Write("Choose a number: ");
string choice = Console.ReadLine();

switch (choice)
{
case "1":
Console.Clear();
Person contact = new Person(
GetString("Please enter your name: "),
GetNum("Please enter your number: "),
GetString("Please enter your address: ")
);

if(myPhonebook.Add(contact))
Console.WriteLine("Your contact added successfully.");
else
Console.WriteLine("Fail!");

break;
case "2":
myPhonebook.SearchByName(GetString("Please enter the name: "));
break;
case "3":
Console.Clear();
myPhonebook.ShowContacts();
break;
case "4":
Environment.Exit(0);
break;
default:
Console.WriteLine("Invalid Input!");
break;
}
Console.ReadLine();
}
}
static string GetString(string message)
{
Console.Write(message);
return Console.ReadLine();
}
static int GetNum(string message)
{
Console.Write(message);
return Convert.ToInt32(Console.ReadLine());
}
}
class Person
{
string Name;
int Number;
string Address;

public Person(string name, int number, string address)
{
Name = name;
Number = number;
Address = address;
}

public string GetName() { return Name; }
public int GetNumber() { return Number; }
public string GetAddress() { return Address; }
}
class Phonebook
{
Person[] Persons;
int Current;
bool Found;

public Phonebook(int size)
{
Persons = new Person[size];
Current = 0;
}

public bool Add(Person person)
{
if (Current < Persons.Length)
{
Persons[Current] = person;
Current++;
return true;
}
return false;
}
public void SearchByName(string search)
{
Found = false;
for (int i = 0; i < Persons.Length; i++)
{
if (Persons[i] == null) break;
if (search == Persons[i].GetName())
{
Found = true;
Console.WriteLine();
Console.WriteLine(Persons[i].GetName() + "\n" + Persons[i].GetNumber() +
"\n" + Persons[i].GetAddress());
}
}
if(!Found)
Console.WriteLine("Not Found!");
}
public void ShowContacts()
{
for (int i = 0; i < Persons.Length; i++)
{
if (Persons[i] == null) return;
Console.WriteLine(Persons[i].GetName() + "\n" + Persons[i].GetNumber() +
"\n" + Persons[i].GetAddress() + "\n");
}
}
}
همان‌طور که مي‌بينيد نسبت به قبل از اشياء و کلاس‌هاي بيشتري استفاده کرديم و اين برنامه را بيشتر به سمت شي‌گرايي سوق داديم. در کلاس Person سه instance variable تعريف کرده‌ايم که هر سه private و شامل نام، آدرس و شماره تلفن هستند. همچنين از constructor براي مقداردهي به اين سه متغير استفاده کرده و از طريق متدهاي public اين متغيرها را Read-only کرديم. در کلاس Phonebook آرايه‌اي از جنس کلاس Person داريم. با اين‌کار در هر خانه‌ي آرايه، يک شيء از جنس Person ذخيره مي‌شود که شامل نام، آدرس و شماره تلفن است. از طريق constructor اين کلاس، آرايه ساخته و مقدار دهي مي‌شود. کلاس Phonebook همچنين شامل سه متد براي جستجو، افزودن مخاطب جديد و نمايش مخاطبان ذخيره شده دارد. همان‌طور که مي‌بينيد، متد ()Add يک شيء از جنس Person دريافت مي‌کند و آن را در آرايه‌اي که از جنس Person ساخته بوديم ذخيره مي‌کند و در نهايت اگر با موفقيت مخاطب جديد را ذخيره کرد، مقدار true را باز مي‌گرداند. در متد ()Main براي افزودن مخاطب جديد، يک شيء از کلاس Person ساخته و argument هاي لازم را به آن داده‌ايم. سپس متد ()Add را صدا زده‌ايم تا مخاطب جديد ذخيره شود.

برچسب‌ها:
نوشته شده در چهارشنبه 23 مرداد 1392 ساعت 14:58 توسط : padideh | دسته : | 202 بازدید
  • []


  • سفارش تبليغات
    سفر به ترکیه | فرش کاشان | آژانس هواپیمایی | منزل مبله در شیراز | کفسابی | هتل و اقامت | آموزش بازاریابی | میز کانتر | گیت کنترل تردد | نوبت دهی پزشکان شیراز | پاپ آپ نمایشگاهی | دکتر نوروزیان | منزل مبله شیراز | طلایاب | سفر به تایلند| ثبت شرکت | راهنمای سفر | سفر به گرجستان | سفر به روسیه | منزل مبله | فلزیاب | محمد دبیری
    X
    تبليغات