الكلمة المفتاحية final
جزء من قسم البرمجة كائنية التوجه في رحلة Java على Coddy. الدرس 13 من 87.
تمنع الكلمة المفتاحية final في Java التعديل. ويمكن تطبيقها على المتغيرات والأساليب والفئات، ويكون لكل منها تأثير مختلف.
عند تطبيقه على متغير، تجعل final منه ثابتًا - فبعد إسناد قيمة إليه، لا يمكن تغييرها:
public class Circle {
private final double PI = 3.14159;
private final double radius;
public Circle(double radius) {
this.radius = radius; // يمكن إسناد قيمة مرة واحدة في المُنشئ
}
public void setRadius(double r) {
// this.radius = r; // خطأ! لا يمكن إعادة إسناد قيمة إلى متغير final
}
}يجب تهيئة المتغير final إما عند التصريح عنه أو في المُنشئ. بعد ذلك، تؤدي أي محاولة لإعادة تعيينه إلى حدوث خطأ في الترجمة.
بالنسبة إلى الأنواع المرجعية، تعني final أن المرجع لا يمكنه الإشارة إلى كائن مختلف، لكن محتويات الكائن لا يزال بإمكانها التغيّر:
private final StringBuilder name = new StringBuilder("John");
// name = new StringBuilder("Jane"); // خطأ! لا يمكن إعادة الإسناد
name.append(" Doe"); // حسنًا! يمكن تغيير محتويات الكائنيوضح استخدام final مع الحقول المقصود بوضوح؛ فهو يخبر المطورين الآخرين بأن هذه القيمة يجب ألا تتغير مطلقًا بعد التهيئة. ويكون هذا مفيدًا خصوصًا لقيم الإعدادات أو المعرّفات أو أي بيانات يجب أن تظل ثابتة طوال عمر الكائن.
لا يمكن تجاوز الطريقة final في صنف فرعي:
class Base {
public final void greet() {
System.out.println("Hi");
}
}
class Child extends Base {
// public void greet() { } // خطأ! greet() هي final في Base
}لا يمكن توسيع الصنف final مطلقًا. الصنف String صنف نهائي، لذا لا يمكن لأي صنف توسيعه:
final class Config { }
// class MyConfig extends Config { } // خطأ! Config هي finalالتحدي
سهللنبنِ نظام تسجيل Student يستخدم الكلمة المفتاحية final لحماية البيانات التي يجب ألا تتغير أبدًا بعد تسجيل الطالب.
ستنشىء ملفين لتنظيم الشيفرة البرمجية:
Student.java: أنشئ فئة Student تُثبَّت فيها بعض المعلومات نهائيًا بمجرد تعيينها:- حقل
finalباسمstudentId(String) - يُعيَّن عند الإنشاء ولا يمكن تغييره أبدًا - حقل
finalباسمenrollmentYear(int) - سنة التحاق الطالب، وهي دائمة أيضًا - حقل خاص عادي باسم
name(String) - يمكن تحديثه إذا غيّر الطالب اسمه - منشئ يأخذ القيم الثلاث ويهيئ الحقول
- دالة getter باسم
getStudentId()لمعرّف الطالب - دالة getter باسم
getEnrollmentYear()لسنة الالتحاق - دالة getter باسم
getName()ودالة setter باسمsetName()للاسم - دالة باسم
getInfo()تُرجع:"ID: [studentId] | Name: [name] | Enrolled: [enrollmentYear]"
- حقل
Main.java: أنشئ كائنًا من فئة Student، ثم حدّث اسمه واعرض معلوماته. ستتلقى أربعة مدخلات: معرّف الطالب، والاسم الأولي، وسنة الالتحاق، والاسم الجديد المراد التحديث إليه. اطبع سطرين:- معلومات الطالب قبل تغيير الاسم
- معلومات الطالب بعد تغيير الاسم
ستتلقى أربعة مدخلات بالترتيب: studentId (String)، وname (String)، وenrollmentYear (int)، وnewName (String).
لاحظ كيف تحمي حقول final معرّف الطالب وسنة التحاقه؛ فهما سجلان دائمان يجب ألا يتغيرا، بينما يمكن تحديث الاسم باستخدام دالة setter الخاصة به.
جرّب بنفسك
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// اقرأ المدخلات
String studentId = scanner.nextLine();
String name = scanner.nextLine();
int enrollmentYear = scanner.nextInt();
scanner.nextLine(); // استهلك محرف السطر الجديد
String newName = scanner.nextLine();
// TODO: أنشئ كائنًا من Student بالقيم الأولية
// TODO: اطبع معلومات الطالب قبل تغيير الاسم
// TODO: حدّث اسم الطالب باستخدام دالة الضبط
// TODO: اطبع معلومات الطالب بعد تغيير الاسم
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات الـ OOP
الملفات الخارجيةمقدمة في الـ OOPالفئات (Classes) مقابل الكائنات (Objects)الكلمة المفتاحية thisالدوال (Methods)الحقول (Attributes)دالة البناء (Constructor)تعدد أشكال دالة البناء (Constructor Overloading)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسية (extends)الكلمة المفتاحية superإعادة تعريف الدوال (@Override)تسلسل المنشئات (Constructor Chaining)كلاس Objectالوراثة الأحادية ومتعددة المستوياتلماذا لا توجد وراثة متعددة للكلاساتمراجعة - هيكلية الموظفين7الدوال الخاصة وفئة Object
دالة toString()equals() و hashCode()دالة clone()compareTo() و Comparableواجهة Comparatorمراجعة - الترتيب المخصص2محددات الوصول والتغليف
نظرة عامة على مستويات الوصولدوال Getter و Setterإخفاء البياناتالكلمة المفتاحية finalمراجعة - مدير الحساب البنكي5تعدد الأشكال (Polymorphism)
أساسيات الـ Method Overloadingالـ Method Overriding (في وقت التشغيل)الـ Upcasting والـ Downcastingمعامل الـ instanceofالفئات والدوال المجردة (Abstract)مراجعة - حاسبة الأشكال8مفاهيم OOP المتقدمة
الـ Composition مقابل الـ Inheritanceالـ Aggregation مقابل الـ Compositionالفئات الداخلية والمتداخلة والمجهولة (Inner, Nested & Anonymous)الـ Enums ودوالهاالـ Records (Java 16+)الـ Sealed Classes (Java 17+)11أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factoryنمط Builderنمط Observerنمط Strategy3خصائص الفئة والعضو الساكن
المتغيرات الخاصة بالكائن مقابل المتغيرات الساكنةالدوال الساكنةالكتل البرمجية الساكنةالثوابت (static final)ملخص - العداد والأدوات المساعدة6الواجهات (Interfaces) والأصناف المجردة (Abstract Classes)
مقدمة في الواجهات (Interfaces)تنفيذ الواجهات (Interfaces)تنفيذ واجهات متعددةالـ Default و Static في الواجهاتالأصناف المجردة مقابل الواجهاتالواجهات الوظيفية (Functional Interfaces)مراجعة - نظام الدفع9الأنواع العامة (Generics)
مقدمة في الأنواع العامةالأصناف العامة (Generic Classes)الدوال العامة (Generic Methods)معاملات الأنواع المقيدةالرموز البديلة (?, extends, super)مراجعة - الحاويات العامة12أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المكررتدرّب بنفسك: مترجم Java عبر الإنترنت