الفئات Classes والكائنات Objects
إنشاء فئة في Java باستخدام NetBeans:
تشبه الفئات المخططات التي تحدد بنية الكائنات وسلوكها في Java. فكر فيها كنماذج لبناء كائنات محددة ذات خصائص وقدرات فريدة.
في Apache NetBeans، اتبع الخطوات التالية لإنشاء class جديد:
إعداد مشروع:
- إذهب إلى File >> New Project >> Java Application
- قم بتسمية مشروعك (على سبيل المثال، JavaOOP) وانقر فوق "Finish".
إنشاء Package:
- انتقل إلى قسم Source Package.
- انقر فوق علامة + واختر جديد New > حزمة Java Package.
- قم بتسمية الـpackage الخاصة بك (على سبيل المثال، com.mycompany.javaoop) وانقر فوق "Finish".
إنشاء Class:
- انقر بزر الماوس الأيمن على package التي قمت بإنشائها.
- حدد جديد New > فئة Java Class.
- قم بتسمية الـclass (على سبيل المثال، Main) وانقر فوق "Finish".
الكود:
package com.mycompany.javaoop; public class Main { public static void main(String[] args) { System.out.println("JAVA"); } }
شرح الكود:
- package com.mycompany.javaoop;: يحدد هذا السطر الحزمة التي تنتمي إليها فئتك الرئيسية. يساعد تنظيم الفئات في حزم في الحفاظ على بنية التعليمات البرمجية وتجنب تعارض الأسماء.
– public class Main: هذا يعلن عن فئة عامة تسمى Main. يمكن الوصول إلى الـclasses العامة من أجزاء أخرى من مشروعك.
– public static void main(String[] args): هذه هي الطريقة الرئيسية main، وهي نقطة الدخول حيث يبدأ تنفيذ برنامجك.
- System.out.println("JAVA");: يطبع هذا السطر النص "JAVA" على شاشة المخرجات.
استكشاف الأخطاء وإصلاحها:
: إذا واجهت هذا الخطأ، فتأكد من تعيين حقل Main Class فيRun configuration على com.mycompany.javaoop.Main.
فيما يلي كيفية معالجة الخطأ "No main classes found" في NetBeans:
- انقر بزر الماوس الأيمن على اسم المشروع (في هذه الحالة، "JavaOOP") في نافذة المشاريع.
- حدد خصائص Properties.
- انتقل إلى فئة Run.
- في حقل Main Class، أدخل الاسم المؤهل بالكامل لmain class، بما في ذلك اسم الـ package. على سبيل المثال، إذا كان اسم الفئة "Main" وكان موجودًا في الحزمة "com.mycompany.javaoop"، فيمكنك إدخال com.mycompany.javaoop.Main.
- انقر OK لحفظ التغييرات.
الآن حاول تشغيل البرنامج مرة أخرى. يجب أن يتم تنفيذه دون ظهور الخطأ "No main classes found".
إنشاء الفئات Classes والكائنات Objects:
ملفات منفصلة لفئات منفصلة: تحتاج كل فئة في Java إلى ملف خاص بها، يختلف عن الفئة الرئيسية Main. وهذا يعزز التنظيم والنمطية في التعليمات البرمجية الخاصة بك.
إنشاء Car Class:
- انقر بزر الماوس الأيمن على الحزمة التي تريد إنشاء الفئة الجديدة فيها (على سبيل المثال، com.mycompany.javaoop).
- حدد جديد New > فئة Java Class.
- قم بتسمية الفئة Car (كتابة الحرف الأول بالأحرف الكبيرة هو اصطلاح تسمية Java).
- انقر فوق Finish. يؤدي هذا إلى إنشاء ملف جديد باسم Car.java ضمن الحزمة الخاصة بك.
طريقة تسمية الـ Classes:
- يبدأ اسم الـclass دائمًا بحرف كبير.
- استخدم أسماء وصفية تعكس غرض الـclass(على سبيل المثال، Car, Person, Account).
- تجعل هذه الطريق الكود أكثر قابلية للقراءة وأسهل للفهم.
مثال 1:
class Car { String name; int maxSpeed; float price; int model; }
إعلان الـClass:
- فئة Car – يعلن هذا السطر عن فئة جديدة تسمى Car.
صفات:
- String name؛ - يحدد attribute تسمى name من النوع String. سيتم تخزين اسمcar object.
- int maxSpeed؛ - يحدد attribute تسمى maxSpeed من النوع int. سيتم تخزين السرعة القصوى لجسم السيارة بالكيلومترات في الساعة.
- float price - يحدد attribute تسمى price من النوع float. سيتم تخزين سعر كائن السيارة بتنسيق floating-point.
- int model؛ - يحدد attribute تسمى model من النوع int. سيتم تخزين سنة طراز جسم السيارة.
الآن سنقوم بإنشاء مثيلاتنا لفئة Car في الفئة Main، لأنها نقطة الدخول للبرنامج حيث يبدأ التنفيذ.
public class Main { public static void main(String args[]) { Car c1 = new Car(); c1.name = "Tesla"; c1.maxSpeed = 210; Car c2 = new Car(); c2.name = "Kia"; System.out.println(c1.name); System.out.println(c1.maxSpeed); System.out.println(c2.name); } }
لا يزال هذا الكود يستخدم Car class مع attributes مثل name, maxSpeed, price, وmodel.
Main Class:
- public static void main(String args[]): هذا السطر هو نقطة الدخول لبرنامجك.
- Car c1 = new Car();: يقوم هذا السطر بإنشاء instance جديد لفئة السيارة وتخصيصه للمتغير c1.
- c1.name = "Tesla"؛: يقوم هذا السطر بتعيين name attribute لكائن c1 على "Tesla".
- c1.maxSpeed = 210;: يقوم هذا السطر بتعيين maxSpeed attribute للكائن c1 على 210 كيلومترًا في الساعة.
- Car c2 = new Car();: يقوم هذا السطر بإنشاء instance جديد آخر لفئة السيارة وتخصيصه للمتغير c2.
- c2.name = "Kia"؛: يقوم هذا السطر بتعيين name attribute لكائن c2 على "Kia".
- System.out.println(c1.name);: يطبع هذا السطر قيمة name attribute للكائن c1 إلى شاشة المخرجات، والتي يجب أن تطبع "Tesla".
- System.out.println(c1.maxSpeed);: يطبع هذا الخط قيمة سمة maxSpeed للكائن c1 إلى شاشة المخرجات، والتي يجب أن تطبع "210".
- System.out.println(c2.name);: يطبع هذا السطر قيمة name attribute للكائن2c1 إلى شاشة المخرجات، والتي يجب أن تطبع "Kia".
مثال 2:
Car Class:
class Car { String name; int maxSpeed; float price; int model; void setName(String n) { name = n; } String getName() { return name; } }
- وله أربع سمات: name, maxSpeed, price, and model. لا تظهر هذه السمات في هذا المثال، لكن يمكنها تخزين معلومات حول اسم السيارة والسرعة القصوى والسعر وسنة الطراز.
- وله طريقتان أيضًا:
- setName(String n): تأخذ هذه الطريقة string argument n وتقوم بتعيين سمة اسم السيارة على تلك القيمة.
- getName(): تقوم هذه الطريقة بإرجاع القيمة الحالية لـname attribute السيارة كنص.
Main Class:
public class Main { public static void main(String args[]) { Car c1 = new Car(); c1.name = "Tesla"; c1.setName("KIA"); System.out.println(c1.getName()); } }
- يقوم بإنشاء instance جديد لفئة السيارة ويعينه للمتغير c1.
- يقوم بتعيين سمة اسم السيارة إلى "Tesla" باستخدام التعيين المباشر (c1.name = "Tesla").
- ثم يقوم بالكتابة فوق الاسم عن طريق استدعاء الأسلوب setName باستخدام الوسيطة "KIA". تقوم هذه الطريقة بتغيير سمة الاسم الداخلي للكائن c1.
- وأخيرًا، يقوم بطباعة اسم السيارة باستخدام طريقة getName، التي تسترد القيمة الحالية ("KIA") وتطبعها على شاشة المخرجات.
مثال 3:
Class Car:
class Car { String name; int maxSpeed; float price; int model; void setName(String n) { // Setters/ Mutators name = n; } String getName() { // Getters/ Accessors return name; } void setModel(int m) { if(m >= 2015) model = m; else System.out.println("Sorry, we do not accept this model"); } int getModel() { return model; } }
- Attributes: لا يزال يحتوي على name, maxSpeed, price, and model.
- الطرق Methods:
- Setters: تسمح هذه الطرق بتعيين قيم attribute محددة.
- setName(String n): يضبط سمة الاسم.
- setModel(int m): يضبط سمة النموذج مع التحقق من الصحة، ويقبل فقط الأعوام 2015 أو الأحدث.
- Getters: تسترد هذه الطرق قيم attribute محددة.
- getName (): إرجاع قيمة سمة الاسم.
- getModel (): إرجاع قيمة سمة النموذج.
Main Class:
public class Main { public static void main(String args[]) { Car c1 = new Car(); c1.name = "Tesla"; c1.setModel(2021); System.out.println(c1.getModel()); // 2021 } }
- Car c1 = new Car();: إنشاء كائن سيارة جديد.
- c1.name = "Tesla";: يضبط سمة الاسم لـ c1 باستخدام السلوك الافتراضي (لا حاجة إلى أداة ضبط setter).
- c1.setModel(2021);: تعيين سمة النموذج لـ c1 باستخدام أداة الضبط. نظرًا لأن عام 2021 صالح، فإنه يقوم بتحديث النموذج.
- System.out.println(c1.getModel());: طباعة سمة النموذج لـ c1، والتي يجب أن تنتج "2021".
معدّلات مستوى الوصول Access Level Modifiers في Java
(التحكم في Visibility وEncapsulation)
معدّلات مستوى الوصول هي بنيات أساسية في Java تحدد إمكانية رؤية أعضاء الـclass وإمكانية الوصول إليهم (fields, methods, constructors). إنهم يلعبون دورًا حاسمًا في تعزيز الـencapsulation، وهو مبدأ أساسي للبرمجة الموجهة للكائنات والذي يضمن حماية البيانات والنمطية.
نقاط أساسية:
- Visibility: تشير إلى ما إذا كان عضو الفصل مرئيًا بشكل مباشر وقابل للاستخدام من أجزاء أخرى من الكود.
- Accessibility: تشير إلى القدرة على الوصول مباشرة إلى عضو الفصل دون استخدام آليات خاصة.
أنواع معدّلات مستوى الوصول Access Level Modifiers:
- Public:
الأعضاء المعلنون للعامة يكونون مرئيين ويمكن الوصول إليهم من أي مكان في برنامجك.
استخدم هذا المعدل بحكمة للعناصر التي تحتاج إلى استخدامها على نطاق واسع، ولكن كن حذرًا حتى لا تكشف تفاصيل التنفيذ دون داع. - Private:
الأعضاء الذين تم الإعلان عن خصوصيتهم يكونون مرئيين فقط ويمكن الوصول إليهم داخل الـclass الذي تم تعريفهم فيه.
وهذا يعزز الـencapsulation عن طريق تقييد الوصول المباشر إلى البيانات الداخلية، وتشجيع استخدام الأساليب العامة للتحكم في التفاعلات مع الـclass. - Protected:
الأعضاء الذين تم الإعلان عن حمايتهم يكونون مرئيين ويمكن الوصول إليهم داخل الفئة التي تم تعريفهم فيها، وفئاتها الفرعية في نفس الحزمة، والفئات الفرعية في حزم مختلفة (ولكن ليس مباشرة من الفئات الأخرى في حزم مختلفة).
يعد هذا المعدل مفيدًا لإنشاء فئة أساسية (superclass) مع أعضاء محميين يمكن الوصول إليهم ومن المحتمل أن يتم تجاوزهم بواسطة فئاتها الفرعية، مما يعزز إعادة استخدام التعليمات البرمجية والـinheritance. - Default (Package-Private):
الأعضاء المعلنون دون أي معدّل وصول يكونون مرئيين ويمكن الوصول إليهم ضمن نفس الحزمة (الحزمة التي تحتوي على تعريف الفئة).
وهذا يوفر التوازن بين الرؤية والتحكم في الوصول داخل الحزمة.
مثال 4:
يوضح هذا الكود بشكل فعال المفاهيم الأساسية الموجهة للكائنات مثل التغليف ومعدلات الوصول وتفاعل الكائنات في Java. فهو يوفر أساسًا متينًا لبناء تطبيقات Java أكثر تعقيدًا وقوة.
Car Class:
public class Car { private String name; private int maxSpeed; private float price; private int model; public void setName(String n) { // Setters/ Mutators name = n; } public String getName() { // Getters/ Accessors return name; } public void setModel(int m) { if(m >= 2015) model = m; else System.out.println("Sorry, we do not accept this model"); } public int getModel() { return model; } }
- صفات:
- name: نص خاص يخزن اسم السيارة.
- maxSpeed: خاص لتخزين السرعة القصوى للسيارة.
– price: خاص تخزن سعر السيارة.
- model: خاص بتخزين سنة موديل السيارة. - الطرق Methods:
-setName(String n): أداة ضبط عامة لتعيين اسم السيارة.
- getName(): أداة عامة لاسترداد اسم السيارة.
– setModel(int m): أداة ضبط عامة لتعيين سنة طراز السيارة، بما في ذلك التحقق من الصحة لسنوات 2015 أو ما بعده.
- getModel(): أداة عامة لاسترداد سنة طراز السيارة.
Main Class:
public class Main { public static void main(String args[]) { Car c1 = new Car(); c1.setModel(2021); System.out.println(c1.getModel()); // 2021 } }
- Car c1 = new Car();: إنشاء كائن سيارة جديد باسم c1.
- c1.setModel(2021);: يحاول تعيين نموذج c1 على 2021. نجح هذا لأن 2021 سنة صالحة.
- System.out.println(c1.getModel());: طباعة نموذج c1 على شاشة المخرجات، مما يؤدي إلى طباعة "2021".
نقاط أساسية:
- Encapsulation: تقوم فئة السيارة بتغليف بياناتها باستخدام سمات خاصة، مما يضمن الوصول المتحكم فيه من خلال الطرق العامة.
- التحقق من صحة البيانات: تتضمن طريقة setModel التحقق من الصحة لمنع سنوات النموذج غير الصالحة، وتعزيز سلامة البيانات.
- تفاعل الكائن: توضح الفئة الرئيسية كيفية إنشاء كائن سيارة والتفاعل معه باستخدام أساليبه العامة.
- Setters and Getters: توفر هذه الأساليب طريقة يمكن التحكم فيها لتعديل واسترجاع سمات الكائن، مع الحفاظ على مبادئ التغليف.
إخفاء البيانات
إخفاء البيانات هو أسلوب تطوير برمجيات يستخدم خصيصًا في البرمجة الشيئية (OOP). يضمن إخفاء البيانات الوصول الحصري للبيانات إلى أعضاء الفصل ويحمي سلامة الكائن عن طريق منع التغييرات غير المقصودة أو المقصودة.
لماذا نستخدم هذه التقنية؟
لأنه يمكن أن يكون لدينا العديد من الكائنات التي ستتصل عبر الرسائل وتستخدم طرقًا أخرى.
Encapsulation
التغليف هو آلية لتغليف البيانات (المتغيرات) والتعليمات البرمجية التي تعمل على البيانات (الطرق) معًا كوحدة واحدة. في التغليف، سيتم إخفاء متغيرات الفئة عن الفئات الأخرى، ولا يمكن الوصول إليها إلا من خلال أساليب الفئة الحالية. لذلك، يُعرف أيضًا باسم إخفاء البيانات.
لتحقيق التغليف في جافا:
- قم بتعريف متغيرات الفئة على أنها خاصة.
- توفير أساليب الضبط العامة و getter لتعديل وعرض قيم المتغيرات.