CodeGym /جاوا بلاگ /Random-UR /عکاسی کی مثالیں۔
John Squirrels
سطح
San Francisco

عکاسی کی مثالیں۔

گروپ میں شائع ہوا۔
ہوسکتا ہے کہ آپ کو عام زندگی میں "عکاسی" کے تصور کا سامنا کرنا پڑا ہو۔ یہ لفظ عام طور پر اپنے آپ کو مطالعہ کرنے کے عمل کی طرف اشارہ کرتا ہے۔ پروگرامنگ میں، اس کا ایک ہی معنی ہے - یہ ایک پروگرام کے بارے میں ڈیٹا کا تجزیہ کرنے کا طریقہ کار ہے، اور یہاں تک کہ پروگرام کے چلنے کے دوران، اس کی ساخت اور طرز عمل کو تبدیل کرنا ہے۔ عکاسی کی مثالیں - 1 یہاں اہم بات یہ ہے کہ ہم یہ کام رن ٹائم پر کر رہے ہیں، مرتب وقت پر نہیں۔ لیکن رن ٹائم کے وقت کوڈ کی جانچ کیوں؟ بہر حال، آپ کوڈ کو پہلے ہی پڑھ سکتے ہیں :/ عکاسی کا خیال فوری طور پر واضح نہ ہونے کی ایک وجہ ہے: اس وقت تک، آپ کو ہمیشہ معلوم تھا کہ آپ کن کلاسوں کے ساتھ کام کر رہے ہیں۔ Catمثال کے طور پر، آپ ایک کلاس لکھ سکتے ہیں :
package learn.codegym;

public class Cat {

   private String name;
   private int age;

   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   public void sayMeow() {

       System.out.println("Meow!");
   }

   public void jump() {

       System.out.println("Jump!");
   }

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

@Override
public String toString() {
   return "Cat{" +
           "name='" + name + '\'' +
           ", age=" + age +
           '}';
}

}
آپ اس کے بارے میں سب کچھ جانتے ہیں، اور آپ اس میں موجود فیلڈز اور طریقے دیکھ سکتے ہیں۔ فرض کریں کہ آپ کو اچانک پروگرام میں جانوروں کی دوسری کلاسوں کو متعارف کرانے کی ضرورت ہے۔ Animalآپ شاید سہولت کے لیے پیرنٹ کلاس کے ساتھ کلاس وراثت کا ڈھانچہ تشکیل دے سکتے ہیں ۔ اس سے پہلے، ہم نے ایک ویٹرنری کلینک کی نمائندگی کرنے والی ایک کلاس بھی بنائی تھی، جس میں ہم کسی Animalچیز کو منتقل کر سکتے تھے (والدین کی کلاس کی مثال)، اور پروگرام نے جانور کے ساتھ مناسب سلوک اس بنیاد پر کیا کہ آیا وہ کتا تھا یا بلی۔ اگرچہ یہ سب سے آسان کام نہیں ہیں، پروگرام کمپائل کے وقت کلاسز کے بارے میں تمام ضروری معلومات سیکھنے کے قابل ہے۔ اس کے مطابق، جب آپ طریقہ کار Catمیں ویٹرنری کلینک کلاس کے طریقوں پر کوئی اعتراض پاس کرتے main()ہیں، تو پروگرام پہلے ہی جانتا ہے کہ یہ ایک بلی ہے، کتا نہیں۔ اب تصور کریں کہ ہمیں ایک مختلف کام کا سامنا ہے۔ ہمارا مقصد ایک کوڈ تجزیہ کار لکھنا ہے۔ ہمیں CodeAnalyzerایک طریقہ کے ساتھ ایک کلاس بنانے کی ضرورت ہے: void analyzeObject(Object o)۔ یہ طریقہ ہونا چاہئے:
  • اس کو پاس کردہ آبجیکٹ کی کلاس کا تعین کریں اور کنسول پر کلاس کا نام ڈسپلے کریں۔
  • پاس شدہ کلاس کے تمام شعبوں کے ناموں کا تعین کریں، بشمول نجی، اور انہیں کنسول پر ڈسپلے کریں؛
  • پاس شدہ کلاس کے تمام طریقوں کے ناموں کا تعین کریں، بشمول پرائیویٹ، اور انہیں کنسول پر ڈسپلے کریں۔
یہ کچھ اس طرح نظر آئے گا:
public class CodeAnalyzer {

   public static void analyzeClass(Object o) {

       // Print the name of the class of object o
       // Print the names of all variables of this class
       // Print the names of all methods of this class
   }

}
اب ہم واضح طور پر دیکھ سکتے ہیں کہ یہ کام دوسرے کاموں سے کس طرح مختلف ہے جو آپ نے پہلے حل کیے ہیں۔ ہمارے موجودہ مقصد کے ساتھ، مشکل اس حقیقت میں ہے کہ نہ تو ہم اور نہ ہی پروگرام کو معلوم ہے کہ طریقہ analyzeClass()کار میں کیا منتقل کیا جائے گا۔ اگر آپ ایسا پروگرام لکھتے ہیں، تو دوسرے پروگرامرز اسے استعمال کرنا شروع کر دیں گے، اور وہ اس طریقہ کار میں کچھ بھی پاس کر سکتے ہیں — کوئی معیاری جاوا کلاس یا کوئی دوسری کلاس جو وہ لکھتے ہیں۔ پاس شدہ کلاس میں متعدد متغیرات اور طریقے ہوسکتے ہیں۔ دوسرے لفظوں میں، ہمیں (اور ہمارے پروگرام) کو اندازہ نہیں ہے کہ ہم کن کلاسوں کے ساتھ کام کریں گے۔ لیکن پھر بھی، ہمیں اس کام کو مکمل کرنے کی ضرورت ہے۔ اور یہ وہ جگہ ہے جہاں معیاری Java Reflection API ہماری مدد کے لیے آتا ہے۔ Reflection API زبان کا ایک طاقتور ٹول ہے۔ اوریکل کی آفیشل دستاویزات تجویز کرتی ہیں کہ یہ طریقہ کار صرف تجربہ کار پروگرامرز کو استعمال کرنا چاہیے جو جانتے ہیں کہ وہ کیا کر رہے ہیں۔ آپ جلد ہی سمجھ جائیں گے کہ ہم اس طرح کی وارننگ پہلے سے کیوں دے رہے ہیں :) یہاں ان چیزوں کی فہرست ہے جو آپ Reflection API کے ساتھ کر سکتے ہیں:
  1. کسی چیز کی کلاس کی شناخت/تعین کریں۔
  2. کلاس موڈیفائرز، فیلڈز، طریقے، مستقل، کنسٹرکٹرز اور سپر کلاسز کے بارے میں معلومات حاصل کریں۔
  3. معلوم کریں کہ کون سے طریقے لاگو کردہ انٹرفیس سے تعلق رکھتے ہیں۔
  4. ایک ایسی کلاس کی مثال بنائیں جس کی کلاس کا نام اس وقت تک معلوم نہ ہو جب تک کہ پروگرام پر عمل نہ ہو۔
  5. حاصل کریں اور نام سے ایک مثال کے میدان کی قیمت مقرر کریں.
  6. ایک مثال کے طریقے کو نام سے کال کریں۔
متاثر کن فہرست، ہہ؟ :) نوٹ:عکاسی کا طریقہ کار یہ سب کچھ "اڑتے ہوئے" کر سکتا ہے، قطع نظر اس کے کہ ہم اپنے کوڈ اینالائزر کو کسی بھی چیز کے پاس بھیجتے ہیں! آئیے کچھ مثالوں کو دیکھ کر Reflection API کی صلاحیتوں کو دریافت کریں۔

کسی چیز کی کلاس کی شناخت / تعین کیسے کریں۔

آئیے بنیادی باتوں سے شروع کریں۔ جاوا ریفلیکشن انجن میں داخلے کا نقطہ Classکلاس ہے۔ جی ہاں، یہ واقعی مضحکہ خیز لگ رہا ہے، لیکن یہ وہی ہے جو عکاسی ہے :) Classکلاس کا استعمال کرتے ہوئے، ہم سب سے پہلے ہمارے طریقہ کار میں پاس کردہ کسی بھی چیز کی کلاس کا تعین کرتے ہیں. آئیے ایسا کرنے کی کوشش کریں:
import learn.codegym.Cat;

public class CodeAnalyzer {

   public static void analyzeClass(Object o) {
       Class clazz = o.getClass();
       System.out.println(clazz);
   }

   public static void main(String[] args) {

       analyzeClass(new Cat("Fluffy", 6));
   }
}
کنسول آؤٹ پٹ:

class learn.codegym.Cat
دو باتوں پر توجہ دیں۔ سب سے پہلے، ہم نے جان بوجھ کر Catکلاس کو الگ learn.codegymپیکج میں ڈالا۔ اب آپ دیکھ سکتے ہیں کہ getClass()طریقہ کلاس کا پورا نام لوٹاتا ہے۔ دوسرا، ہم نے اپنے متغیر کا نام دیا clazz۔ یہ تھوڑا سا عجیب لگتا ہے۔ اسے "کلاس" کہنا معنی خیز ہوگا، لیکن جاوا میں "کلاس" ایک محفوظ لفظ ہے۔ مرتب کرنے والا متغیرات کو یہ کہنے کی اجازت نہیں دے گا۔ ہمیں کسی نہ کسی طرح اس کے ارد گرد حاصل کرنا پڑا :) ایک آغاز کے لئے برا نہیں! ہمارے پاس صلاحیتوں کی اس فہرست میں اور کیا تھا؟

کلاس موڈیفائرز، فیلڈز، طریقے، مستقل، کنسٹرکٹرز اور سپر کلاسز کے بارے میں معلومات کیسے حاصل کی جائیں۔

اب چیزیں مزید دلچسپ ہو رہی ہیں! موجودہ کلاس میں، ہمارے پاس کوئی مستقل یا پیرنٹ کلاس نہیں ہے۔ آئیے ایک مکمل تصویر بنانے کے لیے انہیں شامل کریں۔ سب سے آسان پیرنٹ کلاس بنائیں Animal:
package learn.codegym;
public class Animal {

   private String name;
   private int age;
}
اور ہم اپنی Catکلاس کو وارث بنائیں گے Animalاور ایک مستقل شامل کریں گے:
package learn.codegym;

public class Cat extends Animal {

   private static final String ANIMAL_FAMILY = "Feline family";

   private String name;
   private int age;

   // ...the rest of the class
}
اب ہمارے پاس مکمل تصویر ہے! آئیے دیکھتے ہیں کہ عکاسی کرنے کے قابل ہے :)
import learn.codegym.Cat;

import java.util.Arrays;

public class CodeAnalyzer {

   public static void analyzeClass(Object o) {
       Class clazz = o.getClass();
       System.out.println("Class name: " + clazz);
       System.out.println("Class fields: " + Arrays.toString(clazz.getDeclaredFields()));
       System.out.println("Parent class: " + clazz.getSuperclass());
       System.out.println("Class methods: " + Arrays.toString(clazz.getDeclaredMethods()));
       System.out.println("Class constructors: " + Arrays.toString(clazz.getConstructors()));
   }

   public static void main(String[] args) {

       analyzeClass(new Cat("Fluffy", 6));
   }
}
یہ ہے جو ہم کنسول پر دیکھتے ہیں:
Class name:  class learn.codegym.Cat
Class fields: [private static final java.lang.String learn.codegym.Cat.ANIMAL_FAMILY, private java.lang.String learn.codegym.Cat.name, private int learn.codegym.Cat.age]
Parent class: class learn.codegym.Animal
Class methods: [public java.lang.String learn.codegym.Cat.getName(), public void learn.codegym.Cat.setName(java.lang.String), public void learn.codegym.Cat.sayMeow(), public void learn.codegym.Cat.setAge(int), public void learn.codegym.Cat.jump(), public int learn.codegym.Cat.getAge()]
Class constructors: [public learn.codegym.Cat(java.lang.String, int)]
ان تمام تفصیلی کلاس معلومات کو دیکھیں جو ہم حاصل کرنے کے قابل تھے! اور نہ صرف عوامی معلومات، بلکہ نجی معلومات بھی! نوٹ: privateمتغیرات بھی فہرست میں دکھائے جاتے ہیں۔ کلاس کے ہمارے "تجزیہ" کو بنیادی طور پر مکمل سمجھا جا سکتا ہے: ہم analyzeObject()ہر وہ چیز سیکھنے کے لیے طریقہ استعمال کر رہے ہیں جو ہم کر سکتے ہیں۔ لیکن یہ سب کچھ نہیں ہے جو ہم عکاسی کے ساتھ کر سکتے ہیں۔ ہم صرف سادہ مشاہدے تک محدود نہیں ہیں — ہم کارروائی کرنے کے لیے آگے بڑھیں گے! :)

اس کلاس کی مثال کیسے بنائی جائے جس کی کلاس کا نام اس وقت تک معلوم نہ ہو جب تک کہ پروگرام پر عمل نہ ہو۔

آئیے پہلے سے طے شدہ کنسٹرکٹر کے ساتھ شروع کریں۔ ہماری Catکلاس میں ابھی تک ایک نہیں ہے، تو آئیے اسے شامل کریں:
public Cat() {

}
Catعکاسی ( createCat()طریقہ) کا استعمال کرتے ہوئے آبجیکٹ بنانے کا کوڈ یہ ہے :
import learn.codegym.Cat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

   public static Cat createCat() throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException {

       BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
       String className = reader.readLine();

       Class clazz = Class.forName(className);
       Cat cat = (Cat) clazz.newInstance();

       return cat;
   }

public static Object createObject() throws Exception {

   BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
   String className = reader.readLine();

   Class clazz = Class.forName(className);
   Object result = clazz.newInstance();

   return result;
}

   public static void main(String[] args) throws IOException, IllegalAccessException, ClassNotFoundException, InstantiationException {
       System.out.println(createCat());
   }
}
کنسول ان پٹ:

learn.codegym.Cat
کنسول آؤٹ پٹ:

Cat{name='null', age=0}
یہ کوئی غلطی نہیں ہے: کی قدریں nameاور ageکنسول پر ظاہر ہوتی ہیں کیونکہ ہم نے کلاس toString()کے طریقہ کار میں ان کو آؤٹ پٹ کرنے کے لیے کوڈ لکھا تھا۔ Catیہاں ہم ایک کلاس کا نام پڑھتے ہیں جس کا آبجیکٹ ہم کنسول سے بنائیں گے۔ پروگرام اس کلاس کے نام کو پہچانتا ہے جس کا آبجیکٹ بنایا جانا ہے۔ عکاسی کی مثالیں - 3اختصار کی خاطر، ہم نے مناسب استثنیٰ ہینڈلنگ کوڈ کو چھوڑ دیا، جو مثال کے مقابلے میں زیادہ جگہ لے گا۔ ایک حقیقی پروگرام میں، یقیناً، آپ کو ایسے حالات کو ہینڈل کرنا چاہیے جن میں غلط درج کردہ نام شامل ہوں، وغیرہ۔ ڈیفالٹ کنسٹرکٹر بہت آسان ہے، لہذا جیسا کہ آپ دیکھ سکتے ہیں، کلاس کی ایک مثال بنانے کے لیے اسے استعمال کرنا آسان ہے :) طریقہ استعمال کرتے newInstance()ہوئے ، ہم اس کلاس کا ایک نیا آبجیکٹ بناتے ہیں۔ یہ اور بات ہے کہ Catکنسٹرکٹر دلائل کو بطور ان پٹ لیتا ہے۔ آئیے کلاس کے ڈیفالٹ کنسٹرکٹر کو ہٹا دیں اور اپنے کوڈ کو دوبارہ چلانے کی کوشش کریں۔
null
java.lang.InstantiationException: learn.codegym.Cat
at java.lang.Class.newInstance(Class.java:427)
کچھ غلط ہو گیا! ہمیں ایک خرابی ہوئی کیونکہ ہم نے ڈیفالٹ کنسٹرکٹر کا استعمال کرتے ہوئے ایک آبجیکٹ بنانے کے لیے ایک طریقہ کا مطالبہ کیا۔ لیکن اب ہمارے پاس ایسا کنسٹرکٹر نہیں ہے۔ لہذا جب newInstance()طریقہ چلتا ہے، عکاسی کا طریقہ کار ہمارے پرانے کنسٹرکٹر کو دو پیرامیٹرز کے ساتھ استعمال کرتا ہے:
public Cat(String name, int age) {
   this.name = name;
   this.age = age;
}
لیکن ہم نے پیرامیٹرز کے ساتھ کچھ نہیں کیا، گویا ہم ان کے بارے میں بالکل بھول گئے ہیں! کنسٹرکٹر کو دلائل دینے کے لئے عکاسی کا استعمال کرتے ہوئے تھوڑی سی "تخلیقی صلاحیت" کی ضرورت ہوتی ہے۔
import learn.codegym.Cat;

import java.lang.reflect.InvocationTargetException;

public class Main {

   public static Cat createCat()  {

       Class clazz = null;
       Cat cat = null;

       try {
           clazz = Class.forName("learn.codegym.Cat");
           Class[] catClassParams = {String.class, int.class};
           cat = (Cat) clazz.getConstructor(catClassParams).newInstance("Fluffy", 6);
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       } catch (InstantiationException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       } catch (NoSuchMethodException e) {
           e.printStackTrace();
       } catch (InvocationTargetException e) {
           e.printStackTrace();
       }

       return cat;
   }

   public static void main(String[] args) {
       System.out.println(createCat());
   }
}
کنسول آؤٹ پٹ:

Cat{name='Fluffy', age=6}
آئیے اپنے پروگرام میں کیا ہو رہا ہے اس پر گہری نظر ڈالیں۔ Classہم نے اشیاء کی ایک صف بنائی ۔
Class[] catClassParams = {String.class, int.class};
وہ ہمارے کنسٹرکٹر کے پیرامیٹرز کے مطابق ہیں (جس میں صرف Stringاور intپیرامیٹرز ہیں)۔ ہم انہیں clazz.getConstructor()طریقہ پر منتقل کرتے ہیں اور مطلوبہ کنسٹرکٹر تک رسائی حاصل کرتے ہیں۔ newInstance()اس کے بعد، ہمیں صرف ضروری دلائل کے ساتھ طریقہ کار کو کال کرنے کی ضرورت ہے ، اور واضح طور پر اعتراض کو مطلوبہ قسم پر ڈالنا نہ بھولیں: Cat۔
cat = (Cat) clazz.getConstructor(catClassParams).newInstance("Fluffy", 6);
اب ہمارا اعتراض کامیابی سے تیار ہو گیا ہے! کنسول آؤٹ پٹ:

Cat{name='Fluffy', age=6}
ساتھ ساتھ آگے بڑھ رہے ہیں :)

نام کے ذریعہ مثال کے فیلڈ کی قیمت کیسے حاصل اور سیٹ کریں۔

تصور کریں کہ آپ کسی دوسرے پروگرامر کی لکھی ہوئی کلاس استعمال کر رہے ہیں۔ مزید برآں، آپ کے پاس اس میں ترمیم کرنے کی اہلیت نہیں ہے۔ مثال کے طور پر، ایک ریڈی میڈ کلاس لائبریری JAR میں پیک کی گئی ہے۔ آپ کلاسز کا کوڈ پڑھ سکتے ہیں، لیکن آپ اسے تبدیل نہیں کر سکتے۔ فرض کریں کہ پروگرامر جس نے اس لائبریری میں ایک کلاس بنائی (یہ ہماری پرانی Catکلاس ہے)، ڈیزائن کو حتمی شکل دینے سے پہلے رات کو کافی نیند لینے میں ناکام رہا، اس نے فیلڈ کے لیے گیٹر اور سیٹٹر کو ہٹا دیا age۔ اب یہ کلاس آپ کے پاس آئی ہے۔ یہ آپ کی تمام ضروریات کو پورا کرتا ہے، کیونکہ آپ کو Catاپنے پروگرام میں صرف اشیاء کی ضرورت ہے۔ لیکن آپ کو ان کے پاس ایک ageفیلڈ کی ضرورت ہے! یہ ایک مسئلہ ہے: ہم فیلڈ تک نہیں پہنچ سکتے، کیونکہ اس میں ترمیم privateکرنے والا ہے، اور گیٹر اور سیٹٹر کو نیند سے محروم ڈیولپر نے حذف کر دیا تھا جس نے کلاس بنائی تھی:/ ٹھیک ہے، عکاسی اس صورتحال میں ہماری مدد کر سکتی ہے! ہمارے پاس کلاس کے کوڈ تک رسائی ہے Cat، لہذا ہم کم از کم یہ جان سکتے ہیں کہ اس میں کون سے فیلڈز ہیں اور انہیں کیا کہا جاتا ہے۔ اس معلومات سے لیس، ہم اپنا مسئلہ حل کر سکتے ہیں:
import learn.codegym.Cat;

import java.lang.reflect.Field;

public class Main {

   public static Cat createCat()  {

       Class clazz = null;
       Cat cat = null;
       try {
           clazz = Class.forName("learn.codegym.Cat");
           cat = (Cat) clazz.newInstance();

           // We got lucky with the name field, since it has a setter
           cat.setName("Fluffy");

           Field age = clazz.getDeclaredField("age");

           age.setAccessible(true);

           age.set(cat, 6);

       } catch (IllegalAccessException e) {
           e.printStackTrace();
       } catch (InstantiationException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       } catch (NoSuchFieldException e) {
           e.printStackTrace();
       }

       return cat;
   }

   public static void main(String[] args) {
       System.out.println(createCat());
   }
}
جیسا کہ تبصرے میں کہا گیا ہے، nameفیلڈ کے ساتھ ہر چیز سیدھی ہے، کیونکہ کلاس ڈویلپرز نے ایک سیٹر فراہم کیا ہے۔ آپ پہلے سے ہی جانتے ہیں کہ ڈیفالٹ کنسٹرکٹرز سے اشیاء کیسے بنائیں: ہمارے پاس newInstance()اس کے لیے ہے۔ لیکن ہمیں دوسرے فیلڈ کے ساتھ کچھ ٹنکرنگ کرنا پڑے گا۔ آئیے معلوم کریں کہ یہاں کیا ہو رہا ہے :)
Field age = clazz.getDeclaredField("age");
یہاں، اپنے Class clazzآبجیکٹ کا استعمال کرتے ہوئے، ہم طریقہ ageکے ذریعے فیلڈ تک رسائی حاصل کرتے ہیں۔ getDeclaredField()یہ ہمیں عمر کے میدان کو بطور Field ageآبجیکٹ حاصل کرنے دیتا ہے۔ لیکن یہ کافی نہیں ہے، کیونکہ ہم صرف privateفیلڈز کو قدریں تفویض نہیں کر سکتے۔ ایسا کرنے کے لیے، ہمیں طریقہ استعمال کرکے فیلڈ کو قابل رسائی بنانا ہوگا setAccessible():
age.setAccessible(true);
ایک بار جب ہم اسے کسی فیلڈ میں کرتے ہیں، تو ہم ایک قدر تفویض کر سکتے ہیں:
age.set(cat, 6);
جیسا کہ آپ دیکھ سکتے ہیں، ہمارے Field ageآبجیکٹ میں ایک قسم کا انسائیڈ آؤٹ سیٹر ہوتا ہے جس سے ہم ایک int ویلیو پاس کرتے ہیں اور وہ آبجیکٹ جس کی فیلڈ کو تفویض کیا جانا ہے۔ ہم اپنا main()طریقہ چلاتے ہیں اور دیکھتے ہیں:

Cat{name='Fluffy', age=6}
بہترین! ہم نے کر لیا! :) دیکھتے ہیں ہم اور کیا کر سکتے ہیں...

کسی مثال کے طریقہ کو نام سے کیسے پکارا جائے۔

آئیے پچھلی مثال میں صورتحال کو قدرے تبدیل کرتے ہیں۔ ہم کہتے ہیں کہ Catکلاس ڈویلپر نے گیٹرز اور سیٹرز کے ساتھ کوئی غلطی نہیں کی۔ اس سلسلے میں سب کچھ ٹھیک ہے۔ اب مسئلہ مختلف ہے: ایک طریقہ ہے جس کی ہمیں ضرور ضرورت ہے، لیکن ڈویلپر نے اسے نجی بنا دیا:
private void sayMeow() {

   System.out.println("Meow!");
}
اس کا مطلب ہے کہ اگر ہم اپنے پروگرام میں آبجیکٹ بناتے ہیں ، تو ہم ان پر میتھڈ کو Catکال نہیں کر پائیں گے ۔ sayMeow()ہمارے پاس بلیاں ہوں گی جو میانو نہیں کرتی ہیں؟ یہ عجیب ہے :/ ہم اسے کیسے ٹھیک کریں گے؟ ایک بار پھر، Reflection API ہماری مدد کرتا ہے! ہمیں اس طریقہ کا نام معلوم ہے جس کی ہمیں ضرورت ہے۔ باقی سب کچھ تکنیکی ہے:
import learn.codegym.Cat;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {

   public static void invokeSayMeowMethod()  {

       Class clazz = null;
       Cat cat = null;
       try {

           cat = new Cat("Fluffy", 6);

           clazz = Class.forName(Cat.class.getName());

           Method sayMeow = clazz.getDeclaredMethod("sayMeow");

           sayMeow.setAccessible(true);

           sayMeow.invoke(cat);

       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       } catch (NoSuchMethodException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       } catch (InvocationTargetException e) {
           e.printStackTrace();
       }
   }

   public static void main(String[] args) {
       invokeSayMeowMethod();
   }
}
یہاں ہم وہی کچھ کرتے ہیں جو ہم نے نجی فیلڈ تک رسائی کے وقت کیا تھا۔ سب سے پہلے، ہمیں وہ طریقہ ملتا ہے جس کی ہمیں ضرورت ہے۔ یہ ایک Methodآبجیکٹ میں شامل ہے:
Method sayMeow = clazz.getDeclaredMethod("sayMeow");
طریقہ getDeclaredMethod()ہمیں نجی طریقوں تک پہنچنے دیتا ہے۔ اگلا، ہم طریقہ کار کو قابل کال بناتے ہیں:
sayMeow.setAccessible(true);
اور آخر میں، ہم مطلوبہ اعتراض پر طریقہ کو کال کرتے ہیں:
sayMeow.invoke(cat);
یہاں، ہماری میتھڈ کال ایک "کال بیک" کی طرح نظر آتی ہے: ہم کسی چیز کو مطلوبہ طریقہ ( cat.sayMeow()) کی طرف اشارہ کرنے کے لیے مدت استعمال کرنے کے عادی ہیں، لیکن جب عکاسی کے ساتھ کام کرتے ہیں، تو ہم اس طریقے سے گزر جاتے ہیں جس پر ہم کال کرنا چاہتے ہیں۔ وہ طریقہ. ہمارے کنسول پر کیا ہے؟

Meow!
سب کچھ کام کیا! :) اب آپ ان وسیع امکانات کو دیکھ سکتے ہیں جو جاوا کا ریفلیکشن میکانزم ہمیں دیتا ہے۔ مشکل اور غیر متوقع حالات میں (جیسے بند لائبریری سے کلاس کے ساتھ ہماری مثالیں)، یہ واقعی ہماری بہت مدد کر سکتی ہے۔ لیکن، کسی بھی عظیم طاقت کی طرح، یہ بڑی ذمہ داری لاتا ہے۔ عکاسی کے نقصانات کو اوریکل ویب سائٹ پر ایک خاص حصے میں بیان کیا گیا ہے۔ تین اہم نقصانات ہیں:
  1. کارکردگی بدتر ہے۔ عکاسی کا استعمال کرتے ہوئے کہلائے جانے والے طریقوں کی کارکردگی عام طریقے سے کہے جانے والے طریقوں سے بدتر ہوتی ہے۔

  2. حفاظتی پابندیاں ہیں۔ عکاسی کا طریقہ کار ہمیں رن ٹائم کے وقت پروگرام کے رویے کو تبدیل کرنے دیتا ہے۔ لیکن آپ کے کام کی جگہ پر، ایک حقیقی پروجیکٹ پر کام کرتے وقت، آپ کو ایسی حدود کا سامنا کرنا پڑ سکتا ہے جو اس کی اجازت نہیں دیتی ہیں۔

  3. اندرونی معلومات کی نمائش کا خطرہ۔ یہ سمجھنا ضروری ہے کہ عکاسی انکیپسولیشن کے اصول کی براہ راست خلاف ورزی ہے: یہ ہمیں نجی شعبوں، طریقوں وغیرہ تک رسائی کی اجازت دیتا ہے۔ مجھے نہیں لگتا کہ مجھے یہ بتانے کی ضرورت ہے کہ OOP کے اصولوں کی براہ راست اور واضح خلاف ورزی کا سہارا لیا جانا چاہئے۔ صرف انتہائی انتہائی صورتوں میں، جب آپ کے قابو سے باہر وجوہات کی بنا پر کسی مسئلے کو حل کرنے کے کوئی اور طریقے نہ ہوں۔

سوچ سمجھداری سے استعمال کریں اور صرف ان حالات میں جہاں اس سے گریز نہیں کیا جا سکتا، اور اس کی خامیوں کو نہ بھولیں۔ اس کے ساتھ ہی ہمارا سبق ختم ہو گیا۔ یہ کافی لمبا نکلا، لیکن آج آپ نے بہت کچھ سیکھا :)
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION