الأربعاء، 1 يوليو 2009

interface & Reflection

ٌٌٌReflection

اكتشاف الدوال والفصائل 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


قمنا باستخدام الحزمة 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()




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;
}



كود
class Salary{
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);
}
}





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();
}
}

في الكونستراكتور الاول قمنا بجعله يستقبل قيمة واحدة 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);
}


هذا الشكل صحيح لكن نلاحظ اننا كررنا خطوات الكونستراكتور الاول

ومن اهم مميزات التي قدمتها 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;
}

}


كما نرى فقد قمنا بكتابة دالتين تحملان نفس الاسم ولكن تحتلفان في عدد المعاملات وانواعهم

اذا عدد معاملات الدالة وانواعهم يسميان بصمة الدالة Class Signature

الكونستراكتور ايضا عند تعريف اكثر من واحد يطبق نظرية Overloading

ولكن الفرق بين الكونستراكتور والدالة العادية ان الكونستراكتور لا يرجع قيمة return

ليست هناك تعليقات:

إرسال تعليق