تقييد الوصول إلى الخصائص
يمكن للفئة تحديد كيفية الوصول إلى كل عضو من أعضائها للتعليمات البرمجية خارج الفئة. يمكن إخفاء الأساليب والمتغيرات التي لا يقصد استخدامها من خارج الفئة أو التجميع للحد من احتمال أخطاء الترميز أو الاستغلال الضار.
من المفترض أن يتم استدعاء بعض الأساليب والخصائص أو الوصول إليها من التعليمات البرمجية خارج فئة، والمعروفة باسم التعليمات البرمجية للعميل. قد تكون الأساليب والخصائص الأخرى للاستخدام فقط في الفئة نفسها. من المهم الحد من إمكانية الوصول إلى التعليمات البرمجية الخاصة بك بحيث يمكن فقط للتعليمة البرمجية للعميل المقصود الوصول إليها. يمكنك تحديد كيفية الوصول إلى أنواعك وأعضائها إلى التعليمات البرمجية للعميل باستخدام معدلات الوصول التالية:
-
public: يمكن الوصول إلى النوع أو العضو بواسطة أي تعليمة برمجية أخرى في نفس التجميع أو تجميع آخر يشير إليه. -
protected: يمكن الوصول إلى النوع أو العضو فقط بواسطة التعليمات البرمجية في نفس الفئة أو فئة مشتقة. -
internal: يمكن الوصول إلى النوع أو العضو بواسطة أي تعليمة برمجية في نفس التجميع، ولكن ليس من تجميع آخر. -
protected internal: يمكن الوصول إلى النوع أو العضو بواسطة أي تعليمة برمجية في نفس التجميع، أو بواسطة أي فئة مشتقة في تجميع آخر. -
private: يمكن الوصول إلى النوع أو العضو فقط بواسطة التعليمات البرمجية في نفس الفئة أو البنية. -
private protected: يمكن الوصول إلى النوع أو العضو فقط بواسطة التعليمات البرمجية في نفس التجميع، فقط بواسطة التعليمات البرمجية في نفس الفئة أو فئة مشتقة.
يتم تعيين أعضاء الفئة private الوصول بشكل افتراضي.
الوصول إلى المعدلات على الخصائص والملحقات
حتى هذه النقطة في الوحدة النمطية، ركزنا على الخصائص التي تتضمن كلا من get وملحقات set. يشار إلى هذه الخصائص باسم خصائص القراءة والكتابة. بالإضافة إلى خصائص القراءة والكتابة، يمكنك إنشاء خصائص للقراءة فقط، أو منح إمكانية وصول مختلفة إلى set وملحقات get.
بشكل افتراضي، تتمتع get والملحقات set بنفس مستوى إمكانية وصول ذوي الاحتياجات الخاصة مثل الخاصية التي تنتمي إليها. ومع ذلك، يمكنك تقييد إمكانية وصول get أو ملحق set. تكون معدلات الوصول مفيدة عندما تريد تقييد الوصول إلى الخاصية نفسها، ولكنها لا تزال تسمح بالوصول إلى قيمة الخاصية من خلال ملحق get.
لنفترض أن لديك فئة Person يجب أن تمكن تغيير قيمة الخاصية FirstName فقط من الأساليب الأخرى في الفئة. يمكنك منح إمكانية الوصول الخاصة لملحق set بدلا من إمكانية الوصول الداخلية أو العامة:
public class Person
{
public string? FirstName { get; private set; }
// Omitted for brevity.
}
يمكن قراءة خاصية FirstName من أي تعليمة برمجية، ولكن يمكن تعيينها فقط من التعليمات البرمجية في فئة Person.
يمكنك إضافة أي تعديل وصول مقيد إلى set أو get الملحقة. يجب أن يكون معدل الوصول على ملحق فردي أكثر تقييدا من الوصول إلى الخاصية. التعليمات البرمجية السابقة قانونية لأن الخاصية FirstNamepublic، ولكن ملحق setprivate. تعذر عليك الإعلان عن خاصية private مع ملحق public. يمكن أيضا الإعلان عن إعلانات الخصائص protectedأو internalأو protected internalأو حتى private.
هناك تعديلان خاصان للوصول لملحقات set:
- يمكن أن يحتوي ملحق
setعلىinitكمعدل الوصول الخاص به. يمكن استدعاء هذا الملحقsetفقط من تهيئة كائن أو منشئات النوع. إنه أكثر تقييدا منprivateعلى ملحقset. - يمكن للخاصية التي يتم تنفيذها تلقائيا الإعلان عن ملحق
getبدون ملحقset. في هذه الحالة، يسمح المحول البرمجي باستدعاء ملحقsetفقط من الدالات الإنشائية للنوع. إنه أكثر تقييدا من ملحقinitعلى ملحقset.
خذ بعين الاعتبار التحديثات التالية لفئة الشخص:
public class Person
{
public Person(string firstName) => FirstName = firstName;
public string FirstName { get; }
// Omitted for brevity.
}
يتطلب المثال السابق من المتصلين استخدام الدالة الإنشائية التي تتضمن المعلمة FirstName. لا يمكن للمتصلين استخدام مهايئات الكائنات لتعيين قيمة للخاصية . لدعم المهايئات، يمكنك جعل ملحق set ملحقا init، كما هو موضح في التعليمات البرمجية التالية:
public class Person
{
public Person() { }
public Person(string firstName) => FirstName = firstName;
public string? FirstName { get; init; }
// Omitted for brevity.
}
غالبا ما تستخدم هذه المعدلات مع معدل required لفرض التهيئة المناسبة.
تقييد إمكانية وصول ذوي الاحتياجات الخاصة إلى الملحق
في بعض الحالات، من المفيد تقييد الوصول إلى ملحق get أو set. عادة ما تقوم بتقييد إمكانية الوصول إلى ملحق set، مع الحفاظ على إمكانية الوصول إلى ملحق get بشكل عام.
على سبيل المثال:
private string _name = "Hello";
public string Name
{
get
{
return _name;
}
protected set
{
_name = value;
}
}
في هذا المثال، تحدد خاصية تسمى Nameget وملحق set. يتلقى ملحق get مستوى إمكانية وصول ذوي الاحتياجات الخاصة للخاصية نفسها، public في هذه الحالة، بينما يتم تقييد ملحق set بشكل صريح عن طريق تطبيق معدل الوصول protected على الملحق نفسه.
القيود المفروضة على معدلات الوصول على الملحقات
يخضع استخدام المعدلات الملحقة على الخصائص أو المفهرسات لهذه الشروط:
- يمكنك استخدام معدلات الملحقات فقط إذا كانت الخاصية تحتوي على ملحقات
setوملحقاتget. في هذه الحالة، يسمح المعدل على واحد فقط من الملحقين. - يجب أن يكون مستوى إمكانية الوصول على الملحق أكثر تقييدا من مستوى إمكانية وصول ذوي الاحتياجات الخاصة على الخاصية أو المفهرس نفسه.
خصائص ثابتة للقراءة فقط
يوضح المثال التالي استخدام المثيل والخصائص الثابتة في فئة.
تحتوي فئة Employee على خاصية ثابتة تسمى Counter تتعقب عدد مثيلات الفئة التي تم إنشاؤها. خاصية Counter للقراءة فقط، ما يعني أنه يمكن الوصول إليها من خارج الفئة ولكن لا يمكن تعديلها. يتم أيضا Counterالخاصية static ، مما يعني أنك تصل إلى قيمة Counter باستخدام فئة Employee، وليس مثيلات employee1 أو employee2 للفئة.
public class Employee
{
public static int NumberOfEmployees;
private static int _counter;
private string _name;
// A read-write instance property:
public string Name
{
get => _name;
set => _name = value;
}
// A read-only static property:
public static int Counter => _counter;
// A Constructor:
public Employee() => _counter = ++NumberOfEmployees; // Calculate the employee's number:
}
public class Program
{
static void Main(string[] args)
{
// Create an initial instance of the Employee class
Employee employee1 = new Employee { Name = "NameOne" };
// Display the name and counter values
Console.WriteLine($"Employee 1: Name = {employee1.Name}, Counter = {Employee.Counter}");
// Create a second instance of the Employee class
Employee employee2 = new Employee { Name = "NameTwo" };
// Display the name and counter values
Console.WriteLine($"Employee 2: Name = {employee2.Name}, Counter = {Employee.Counter}");
employee2.Name = "NameThree";
// Display the name and counter values
Console.WriteLine($"Employee 2: Name = {employee2.Name}, Counter = {Employee.Counter}");
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
تحتوي الفئة Employee على الأعضاء التالين:
-
NumberOfEmployees: حقل ثابت عام يتعقب العدد الإجمالي لمثيلات الموظف التي تم إنشاؤها. تكون ثابتة، تتم مشاركتها بين جميع مثيلات فئة الموظف. -
_counter: حقل ثابت خاص يستخدم لتعيين رقم فريد لكل مثيل موظف. كما أنها مشتركة بين جميع المثيلات. -
_name: حقل مثيل خاص يخزن اسم الموظف. إنها خاصة بكل مثيل من فئة الموظف. -
Name: خاصية مثيل القراءة والكتابة العامة التي توفر الوصول إلى حقل _name. يقوم ملحقgetبإرجاع قيمة_name، ويعين ملحقsetقيمة جديدة_name. -
Counter: خاصية عامة ثابتة للقراءة فقط توفر الوصول إلى حقل_counter. يقوم ملحقgetبإرجاع قيمة_counter. ترتبط الخاصيةCounterبالفئة بدلا من الكائنات لأنه تم تعريفها كخاصية ثابتة.
تتم تهيئة الحقلين الثابتين عند تحميل الفئة لأول مرة في الذاكرة، قبل إنشاء أي مثيلات للفئة. في C#، تتم تهيئة الحقول الثابتة إلى قيمها الافتراضية إذا لم تتم تهيئتها بشكل صريح. بالنسبة لحقول int، القيمة الافتراضية هي 0.
تنتمي الخصائص والحقول الثابتة إلى الفئة نفسها، وليس إلى أي مثيل معين من الفئة. تشترك جميع مثيلات الفئة في نفس الخصائص والحقول الثابتة.
تقوم الدالة الإنشائية بزيادة الحقل الثابت NumberOfEmployees بمقدار 1 وتعيين القيمة الجديدة للحقل الثابت _counter. يضمن هذا الأسلوب حصول كل مثيل Employee على رقم فريد.
الملحقات الخاصة
خذ بعين الاعتبار التعليمات البرمجية التالية التي تنفذ خصائص القراءة والكتابة:
class Person
{
private string _name = "N/A";
private int _age = 0;
// Declare a Name property of type string:
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
// Declare an Age property of type int:
public int Age
{
get
{
return _age;
}
set
{
_age = value;
}
}
}
class TestPerson
{
static void Main()
{
// Create a new Person object:
Person person = new Person();
// Print out the name and the age associated with the person:
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Set some values on the person object:
person.Name = "NameOne";
person.Age = 99;
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Increment the Age property:
person.Age += 1;
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Person details - Name = N/A, Age = 0
Person details - Name = NameOne, Age = 99
Person details - Name = NameOne, Age = 100
*/
في هذا المثال، تتضمن فئة Person خصائص NameAge. الخصائص عامة وتتضمن كل من get وملحقات set. تسمح الملحقات العامة لأي كائن بقراءة هذه الخصائص وكتابتها.
في بعض الأحيان يكون لاستبعاد أحد الملحقات. يمكنك حذف ملحق set لجعل الخاصية للقراءة فقط:
public string Name
{
get
{
return _name;
}
}
بدلا من ذلك، يمكنك كشف أحد الملحقات بشكل عام ولكن جعل الآخر خاصا أو محميا.
public string Name
{
get
{
return _name;
}
private set
{
_name = value;
}
}