اكتشاف الدوال والفصائل Classes بعملية الـ ٌٌٌReflection
عملية ال ٌٌٌReflection والتي تسمى ايضا introspection تجعل class ما قادرة على معرفة تفاصيل اي class
مثل المتغيرات الموجودة بها ودوال البناء Constructor وانواعها
لنرى ذلك في المثال التالي
كود
import java.lang.reflect.*;
import java.util.Random;
class Test{
public static void main(String arg[]){
Random r = new Random();
Class c = r.getClass();
Method []method= c.getMethods();
for (int i = 0; i
import java.util.Random;
class Test{
public static void main(String arg[]){
Random r = new Random();
Class c = r.getClass();
Method []method= c.getMethods();
for (int i = 0; i
قمنا باستخدام الحزمة reflect والتي بها مجموعة classes تمكننا من معرفة ودوال وبيانات اي class
بعد ذلك انشأنا object من الفصيلة Random
كود
Class c = r.getClass();
هنا قمنا بعملية ال ٌٌٌReflection و ذلك باستخدام الفصيلة Class حيث تقوم بعملية ادارة البحث عن المعلومات المطلوبة عن فصيلة ما
والتي كانت في المثال Random
بعد ذلك قمنا بطباعة الدوال والمتغيرات
والناتج كالتالي
كود
Method: public int java.util.Random.nextInt(int)
Method: public int java.util.Random.nextInt()
Method: public double java.util.Random.nextDouble()
Method: public boolean java.util.Random.nextBoolean()
Method: public void java.util.Random.nextBytes(byte[])
Method: public float java.util.Random.nextFloat()
Method: public synchronized double java.util.Random.nextGaussi
Method: public long java.util.Random.nextLong()
Method: public synchronized void java.util.Random.setSeed(long
Method: public final void java.lang.Object.wait() throws java.
ception
Method: public final void java.lang.Object.wait(long,int) thro
ruptedException
Method: public final native void java.lang.Object.wait(long) t
terruptedException
Method: public native int java.lang.Object.hashCode()
Method: public final native java.lang.Class java.lang.Object.g
Method: public boolean java.lang.Object.equals(java.lang.Objec
Method: public java.lang.String java.lang.Object.toString()
Method: public final native void java.lang.Object.notify()
Method: public final native void java.lang.Object.notifyAll()
Method: public int java.util.Random.nextInt()
Method: public double java.util.Random.nextDouble()
Method: public boolean java.util.Random.nextBoolean()
Method: public void java.util.Random.nextBytes(byte[])
Method: public float java.util.Random.nextFloat()
Method: public synchronized double java.util.Random.nextGaussi
Method: public long java.util.Random.nextLong()
Method: public synchronized void java.util.Random.setSeed(long
Method: public final void java.lang.Object.wait() throws java.
ception
Method: public final void java.lang.Object.wait(long,int) thro
ruptedException
Method: public final native void java.lang.Object.wait(long) t
terruptedException
Method: public native int java.lang.Object.hashCode()
Method: public final native java.lang.Class java.lang.Object.g
Method: public boolean java.lang.Object.equals(java.lang.Objec
Method: public java.lang.String java.lang.Object.toString()
Method: public final native void java.lang.Object.notify()
Method: public final native void java.lang.Object.notifyAll()
interface
كما نعلم ان لغة JAVA لا تدعم الوراثة المتعددة ولكن في الحياة العملية فان من الممكن ان تحتاج لان تنشئ class ترث خواصها
من اكثر من class اخرى ففي الحياة العادية مثلا الابن يرث صفاته من امه وابيه ولكن في الجافا الوراثة فقط من واحد فما الحل ؟
الحل هو استخدام interface
تعريف interface ::
يتم تعريف interface مثل الclass تماما ولكن مع استبدال كلمة class بكلمة interface
مثال
كود
interface Employee{}
ما يحتويه ال interface
من الممكن ان يحتوي ال interface على متغيرات و دوال ولكن كل المتغيرات فيه تكون final اي لا يمكن تغير قيمتها الابتدائية
وكل الدوال تكون abstract بمعنى انه في ال class التي تستخدم هذا ال interface فانك لابد ان تعيد تعريف جميع الدوال فيه
والا اعتبرت ال class الجديدة abstract و بالتالي لا يمكنك انشاء object منها
لا يمكنك في ال interface كتابة تعريف اي دالة ولكن يكتب نوع القيمة المرتجعة من الدالة وثم اسم الدالة ثم المتغيرات
في الوراثة العادية نستخدم كلمة extends اما في استخدام ال interface نستعمل implements
مثال
كود
interface Employee{
float calculateTax();
int x=10;
}
float calculateTax();
int x=10;
}
كود
class Salary{
float salary;
float Tax;
}
float salary;
float Tax;
}
كود
class Engineer extends Salary implements Employee{
Engineer(float salary,float Tax){
this.salary=salary;
this.Tax=Tax;
}
public float calculateTax(){
return salary*Tax;
//x=20; //this line causes an error
}
public static void main(String arg[]){
Engineer eng = new Engineer(1000,05f);
float f=eng.calculateTax();
System.out.println("Tax= "+f);
}
}
Engineer(float salary,float Tax){
this.salary=salary;
this.Tax=Tax;
}
public float calculateTax(){
return salary*Tax;
//x=20; //this line causes an error
}
public static void main(String arg[]){
Engineer eng = new Engineer(1000,05f);
float f=eng.calculateTax();
System.out.println("Tax= "+f);
}
}
this
المفتاح this له دور كبير مع دوال البناء constructor
وعموما this تشير الي الهدف الحالي ولها اثنان من مواطن الاستخدام وهي
1- this استدعاء دوال البناء
2- تحل مشكلة اسماء المتغيرات المتشابهة
لنرى مثال يوضح لنا الاستخدامان
كود
class Employee
{
String name;
int age;
double salary;
Employee(String name){
this.name=name;
System.out.println("Employee name is "+name);
}
Employee(String name,double sal){
this(name);
salary=sal;
System.out.println("Employee Salary is "+salary);
}
void printAll(){
System.out.println(" name : "+name);
System.out.println(" Salary : "+salary);
}
public static void main(String arg[]){
Employee emp1=new Employee("Mohamed");
emp1.printAll();
Employee emp2=new Employee("Hany",4598.56);
emp2.printAll();
}
}
{
String name;
int age;
double salary;
Employee(String name){
this.name=name;
System.out.println("Employee name is "+name);
}
Employee(String name,double sal){
this(name);
salary=sal;
System.out.println("Employee Salary is "+salary);
}
void printAll(){
System.out.println(" name : "+name);
System.out.println(" Salary : "+salary);
}
public static void main(String arg[]){
Employee emp1=new Employee("Mohamed");
emp1.printAll();
Employee emp2=new Employee("Hany",4598.56);
emp2.printAll();
}
}
في الكونستراكتور الاول قمنا بجعله يستقبل قيمة واحدة name وهي تختلف عن المتغير الذي قمنا بتعريفه في بداية ال class
الان نريد ان نعطي هذه القيمة للمتغير الذي قمنا بتعريفه في داخل ال class
لان الامتغيران يحملان نفس الاسم فلا استطيع عمل التالي
name=name;
لان المترجم سيفهم اننا نريد مساواة المعامل بنفسه ولحل هذه المشكلة قمنا بكتابة التالي
this.name=name;
في هذه الحالة سيفهم المترجم انني اريد ان اشير الي المتغير الخارجي المعرف في بداية ال class وتخصيص القيمة الممررة
من المعامل الي المتغير وبذلك نكون قد حللنا مشكلة اسماء المتغيرات المتشابهة
الكونستراكتور الثاني قمنا بتمرير قيمتين String name,double sal
وكان من المفروض ان نكتب دالة البناء الكونستراكتور بالشكل التالي
كود
Employee(String name,double sal){
this.name=name;
salary=sal;
System.out.println("Employee name is "+name);
System.out.println("Employee Salary is "+salary);
}
this.name=name;
salary=sal;
System.out.println("Employee name is "+name);
System.out.println("Employee Salary is "+salary);
}
هذا الشكل صحيح لكن نلاحظ اننا كررنا خطوات الكونستراكتور الاول
ومن اهم مميزات التي قدمتها OOP انها تجنبنا القيام بتكرار عمل قد قمنا به من قبل
وقدمت لنا ايضا المؤثر this ليقوم باستدعاء الكونستراكتور الاول
this(name);
ومعنى هذه الخطوة انك تريد من المترجم الكمبايلر ان يستدعي الكونستراكتور الاول الذي يمرر قيمة واحدة وهي name
ويشترط في هذه الحالة ان تكون this هي اول جملة في الكونستراكتور كما انه لا يمكننا استخدام this في استدعاء اكثر من كونستراكتور.
Overloading
هو انشاء دوال تحمل نفس الاسم ولكن تختلف في عدد وانواع المعاملات
مثال
كود
class Student{
String name;
int age;
String address;
Student(String name){
this.name=name;
}
public void setInfo(String name){
this.name=name;
}
public void setInfo(String address,int age){
this.address=address;
this.age=age;
}
}
String name;
int age;
String address;
Student(String name){
this.name=name;
}
public void setInfo(String name){
this.name=name;
}
public void setInfo(String address,int age){
this.address=address;
this.age=age;
}
}
كما نرى فقد قمنا بكتابة دالتين تحملان نفس الاسم ولكن تحتلفان في عدد المعاملات وانواعهم
اذا عدد معاملات الدالة وانواعهم يسميان بصمة الدالة Class Signature
الكونستراكتور ايضا عند تعريف اكثر من واحد يطبق نظرية Overloading
ولكن الفرق بين الكونستراكتور والدالة العادية ان الكونستراكتور لا يرجع قيمة return