مرحبًا! في المحاضرات السابقة، تعلمت بالفعل كيفية الإعلان عن فصولك الدراسية الكاملة باستخدام الأساليب والحقول. في درس اليوم، سنتحدث عن Getters وSetters في Java. هذا تقدم جدي، أحسنت! ولكن الآن يجب أن أخبرك بحقيقة غير سارة. لم نعلن عن دروسنا بشكل صحيح! لماذا؟ للوهلة الأولى، لا يحتوي الفصل التالي على أي أخطاء:
تأتي هذه الأسماء من "get" (أي "طريقة للحصول على قيمة الحقل") و"set" (أي "طريقة لتحديد قيمة الحقل"). دعونا نرى كيف تبدو في فئة Cat :
وبدلاً من ذلك، توفر لك الشركة المصنعة واجهة: يقوم المستخدم ببساطة بإدخال الأرقام الصحيحة، والضغط على زر الاتصال الأخضر، وتبدأ المكالمة. إنها لا تهتم بما يحدث بالداخل مع الدوائر والأسلاك، أو كيف يقومون بعملهم. في هذا المثال، تقوم الشركة بتقييد الوصول إلى "الأجزاء الداخلية" (البيانات) للهاتف وتكشف فقط عن الواجهة (الطرق). ونتيجة لذلك، يحصل المستخدم على ما يريده (القدرة على إجراء مكالمة) وبالتأكيد لن يكسر أي شيء بداخله. لتعزيز ما تعلمته، نقترح عليك مشاهدة درس فيديو من دورة Java الخاصة بنا
public class Cat {
public String name;
public int age;
public int weight;
public Cat(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public Cat() {
}
public void sayMeow() {
System.out.println("Meow!");
}
}
لكنها تفعل ذلك. تخيل أنك تجلس في العمل وتكتب فصل Cat هذا لتمثيل القطط. وبعد ذلك تذهب إلى المنزل. أثناء رحيلك، يصل مبرمج آخر إلى العمل. يقوم بإنشاء فصله الرئيسي الخاص ، حيث يبدأ في استخدام فئة Cat التي كتبتها.
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "";
cat.age = -1000;
cat.weight = 0;
}
}
لا يهم لماذا فعل ذلك وكيف حدث (ربما كان الرجل متعبًا أو لم يحصل على قسط كافٍ من النوم). شيء آخر مهم: فئة Cat الحالية لدينا تسمح بتعيين قيم مجنونة تمامًا للحقول. ونتيجة لذلك، يحتوي البرنامج على كائنات ذات حالة غير صالحة (مثل هذه القطة التي يبلغ عمرها -1000 عام). إذن ما الخطأ الذي ارتكبناه عند إعلان صفنا؟ لقد كشفنا عن بيانات صفنا. حقول الاسم والعمر والوزن عامة. يمكن الوصول إليها في أي مكان في البرنامج: ما عليك سوى إنشاء كائن Cat وسيتمتع أي مبرمج بإمكانية الوصول المباشر إلى بياناته من خلال عامل النقطة ( . )
Cat cat = new Cat();
cat.name = "";
نحن هنا نصل مباشرة إلى حقل الاسم ونحدد قيمته. نحن بحاجة إلى حماية بياناتنا بطريقة أو بأخرى من التدخل الخارجي غير المناسب. ماذا نحتاج للقيام بذلك؟ أولاً، يجب وضع علامة على كافة متغيرات المثيل (الحقول) باستخدام المعدل الخاص. الخاص هو معدل الوصول الأكثر صرامة في Java. بمجرد القيام بذلك، لن يكون من الممكن الوصول إلى حقول فئة Cat خارج الفصل.
public class Cat {
private String name;
private int age;
private int weight;
public Cat(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public Cat() {
}
public void sayMeow() {
System.out.println("Meow!");
}
}
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "";//error! The Cat class's name field is private!
}
}
يرى المترجم هذا ويولد خطأ على الفور. الآن أصبحت الحقول محمية نوعًا ما. ولكن اتضح أننا أغلقنا الوصول ربما بشكل محكم للغاية: لا يمكنك الحصول على وزن قطة موجودة في البرنامج، حتى لو كنت بحاجة إلى ذلك. وهذا أيضاً ليس خياراً. كما هو الحال، فإن فصلنا غير قابل للاستخدام بشكل أساسي. من الناحية المثالية، نحتاج إلى السماح بنوع من الوصول المحدود:
- يجب أن يكون المبرمجون الآخرون قادرين على إنشاء كائنات Cat
- يجب أن يكونوا قادرين على قراءة البيانات من الكائنات الموجودة (على سبيل المثال، الحصول على اسم أو عمر قطة موجودة)
- يجب أن يكون من الممكن أيضًا تعيين قيم الحقول. ولكن عند القيام بذلك، ينبغي السماح فقط بالقيم الصالحة. يجب حماية العناصر الخاصة بنا من القيم غير الصالحة (على سبيل المثال، العمر = -1000، وما إلى ذلك).
public class Cat {
private String name;
private int age;
private int weight;
public Cat(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public Cat() {
}
public void sayMeow() {
System.out.println("Meow!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
كما ترون، تبدو بسيطة جدًا :) غالبًا ما تتكون أسماؤهم من "get"/"set" بالإضافة إلى اسم الحقل ذي الصلة. على سبيل المثال، تقوم طريقة getWeight() بإرجاع قيمة حقل الوزن للكائن الذي يتم استدعاؤه عليه. وإليك كيف يبدو في البرنامج:
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
String smudgeName = smudge.getName();
int smudgeAge = smudge.getAge();
int smudgeWeight = smudge.getWeight();
System.out.println("Cat's name: " + smudgeName);
System.out.println("Cat's age: " + smudgeAge);
System.out.println("Cat's weight: " + smudgeWeight);
}
}
إخراج وحدة التحكم:
Cat's name: Smudge
Cat's age: 5
Cat's weight: 4
الآن يمكن لفئة أخرى ( رئيسية ) الوصول إلى حقول Cat ، ولكن فقط من خلال الحروف. لاحظ أن الحاصلين على البيانات لديهم معدل الوصول العام، أي أنهم متاحون من أي مكان في البرنامج. ولكن ماذا عن تعيين القيم؟ هذا هو الغرض من أساليب الضبط
public void setName(String name) {
this.name = name;
}
كما ترون، فهي بسيطة أيضا. نحن نستدعي طريقة setName() على كائن Cat ، ونمرر سلسلة كوسيطة، ويتم تعيين السلسلة إلى حقل اسم الكائن.
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
System.out.println("Cat's original name: " + smudge.getName());
smudge.setName("Mr. Smudge");
System.out.println("Cat's new name: " + smudge.getName());
}
}
نحن هنا نستخدم كلا من الحروف والمستوطنين. أولاً، نستخدم أداة الحصول للحصول على الاسم الأصلي للقطة وعرضه. بعد ذلك، نستخدم أداة ضبط لتعيين اسم جديد ("السيد سمودج"). ثم نستخدم حرف الجلب مرة أخرى للحصول على الاسم (للتحقق مما إذا كان قد تغير بالفعل). إخراج وحدة التحكم:
Cat's original name: Smudge
Cat's new name: Mr. Smudge
إذن ما الفرق؟ لا يزال بإمكاننا تعيين قيم غير صالحة للحقول حتى لو كان لدينا أدوات ضبط:
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
smudge.setAge(-1000);
System.out.println("Smudge's age: " + smudge.getAge());
}
}
إخراج وحدة التحكم:
Smudge's age: -1000 years
الفرق هو أن أداة الضبط هي طريقة كاملة. وعلى عكس الحقل، تتيح لك الطريقة كتابة منطق التحقق الضروري لمنع القيم غير المقبولة. على سبيل المثال، يمكنك بسهولة منع تعيين رقم سالب كعمر:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
System.out.println("Error! Age can't be negative!");
}
}
والآن يعمل الكود الخاص بنا بشكل صحيح!
public class Main {
public static void main(String[] args) {
Cat smudge = new Cat("Smudge", 5, 4);
smudge.setAge(-1000);
System.out.println("Smudge's age: " + smudge.getAge());
}
}
إخراج وحدة التحكم:
Error! Age can't be negative!
Smudge's age: 5 years
داخل أداة الضبط، أنشأنا قيدًا يحمينا من محاولة تعيين بيانات غير صالحة. لم يتغير عمر سمادج. يجب عليك دائمًا إنشاء الحروف والمستوطنين. حتى لو لم تكن هناك قيود على القيم التي يمكن أن تتخذها مجالاتك، فإن هذه الأساليب المساعدة لن تسبب أي ضرر. تخيل الموقف التالي: أنت وزملائك تكتبون برنامجًا معًا. يمكنك إنشاء فئة Cat مع الحقول العامة. جميع المبرمجين يستخدمونها كيفما يريدون. ثم في أحد الأيام تدرك: "تبا، عاجلا أم آجلا قد يقوم شخص ما عن طريق الخطأ بتعيين رقم سالب للوزن! نحن بحاجة إلى إنشاء أدوات ضبط وجعل جميع الحقول خاصة!" أنت تفعل ذلك بالضبط، وتكسر على الفور كل التعليمات البرمجية التي كتبها زملائك. بعد كل شيء، لقد كتبوا بالفعل مجموعة من التعليمات البرمجية التي تصل إلى حقول Cat مباشرة.
cat.name = "Behemoth";
والآن أصبحت الحقول خاصة والمترجم ينشر مجموعة من الأخطاء!
cat.name = "Behemoth";//error! The Cat class's name field is private!
في هذه الحالة، سيكون من الأفضل إخفاء الحقول وإنشاء getter وsetters من البداية. كان جميع زملائك سيستخدمونها. وإذا أدركت متأخرًا أنك بحاجة إلى تقييد قيم الحقول بطريقة أو بأخرى، فمن الممكن أن تكتب الشيك داخل أداة الضبط. ولن يتم كسر رمز أحد. بالطبع، إذا كنت تريد أن يكون الوصول إلى الحقل "للقراءة فقط"، فيمكنك إنشاء أداة الحصول عليه فقط. يجب أن تكون الأساليب فقط متاحة خارجيًا (أي خارج فصلك الدراسي). يجب أن تكون مخفية البيانات. يمكننا إجراء مقارنة مع الهاتف المحمول. تخيل أنه بدلاً من الهاتف المحمول المغلق المعتاد، تم إعطاؤك هاتفًا بحافظة مفتوحة، به جميع أنواع الأسلاك والدوائر البارزة، وما إلى ذلك. لكن الهاتف يعمل: إذا حاولت جاهدًا وخز الدوائر، فقد تفشل قادرة على إجراء مكالمة. لكن من المحتمل أن تكسرها.
GO TO FULL VERSION