আমার প্রতিবিম্ব কেন ব্যবহার করা উচিত?


29

আমি জাভাতে নতুন; আমার অধ্যয়নের মাধ্যমে, আমি পড়লাম যে প্রতিচ্ছবি ক্লাস এবং পদ্ধতিগুলি আহ্বান করতে ব্যবহৃত হয় এবং কোন পদ্ধতিগুলি প্রয়োগ করা হয় বা না তা জানতে।

আমার কখন প্রতিবিম্ব ব্যবহার করা উচিত এবং প্রতিচ্ছবি ব্যবহার এবং অবজেক্টগুলি ইনস্ট্যান্টিয়েট করা এবং traditionalতিহ্যবাহী উপায়ে কল করার পদ্ধতিগুলির মধ্যে পার্থক্য কী?


5
পরীক্ষা করে দেখুন stackoverflow.com/questions/37628/...
Jalayn

10
পোস্ট করার আগে দয়া করে আপনার গবেষণার ভাগ করুন। স্ট্যাকএক্সচেঞ্জে প্রচুর পরিমাণে উপাদান রয়েছে (যেমন জালেন উল্লেখ করেছেন) এবং ওয়েব প্রতিচ্ছবি সম্পর্কে সাধারণভাবে। আমি আপনাকে প্রতিবিম্ব সম্পর্কিত জাভা টিউটোরিয়ালটি পড়ার পরামর্শ দিচ্ছি এবং এর পরে যদি আপনার আরও কোনও কড়া প্রশ্ন থাকে তবে ফিরে আসুন।
পিয়েটার টার্ক

1
সেখানে মিলিয়ন ডুপস থাকতে হবে।
ডেড এমজি

3
কয়েকজন পেশাদার প্রোগ্রামার উত্তর দিয়েছিলেন "যত কমই সম্ভব, সম্ভবত এমনকি কখনওই না"।
রস প্যাটারসন

উত্তর:


38
  • তাদের নাম ধরে কেবল কল করার পদ্ধতিগুলির চেয়ে প্রতিবিম্ব অনেক ধীর, কারণ এটি কেবল প্রাকম্পিল্ড ঠিকানা এবং ধ্রুবক ব্যবহার না করে বাইটকোডে মেটাডেটা পরীক্ষা করতে হবে।

  • প্রতিবিম্বটি আরও শক্তিশালী: আপনি কোনও সদস্য protectedবা finalসদস্যের সংজ্ঞা পুনরুদ্ধার করতে পারেন, সুরক্ষাটি সরিয়ে ফেলতে পারেন এবং এটিকে এমনভাবে চালিত করতে পারেন যেন এটি পরিবর্তনীয় হিসাবে ঘোষণা করা হয়েছিল! স্পষ্টতই এই ভাষাটি আপনার প্রোগ্রামগুলির জন্য সাধারণত গ্যারান্টি দেয় এবং এটি খুব, খুব বিপজ্জনক হতে পারে many

এবং এটি বেশিরভাগ ক্ষেত্রে এটি কখন ব্যবহার করবেন তা ব্যাখ্যা করে। সাধারণত, না। আপনি যদি কোনও পদ্ধতিতে কল করতে চান তবে কেবল এটি কল করুন। আপনি যদি কোনও সদস্যকে রূপান্তর করতে চান তবে কেবল সংকলনের পিছনে না গিয়ে পরিবর্তক হিসাবে ঘোষণা করুন।

প্রতিবিম্বের একটি দরকারী বাস্তব-ব্যবহারের ব্যবহার হ'ল এমন একটি ফ্রেম ফ্রেম লেখার সময় যা ব্যবহারকারী-সংজ্ঞায়িত শ্রেণীর সাথে ইন্টারঅ্যাক্ট করতে হয়, যেখানে ফ্রেমওয়ার্ক লেখক জানেন না যে সদস্যরা (বা এমনকি শ্রেণিগুলি) কী হবে। প্রতিচ্ছবি তাদের অগ্রিম না জেনে কোনও শ্রেণির সাথে ডিল করার অনুমতি দেয়। উদাহরণস্বরূপ, আমি মনে করি না প্রতিফলন ছাড়াই কোনও জটিল দিক-ভিত্তিক গ্রন্থাগার লেখা সম্ভব হবে।

অন্য উদাহরণ হিসাবে, JUnit একটি তুচ্ছ বিট প্রতিবিম্ব ব্যবহার করত: এটি আপনার শ্রেণীর সমস্ত পদ্ধতি গণনা করে, ধরে নেওয়া হয় যে সমস্ত বলা হয়েছে testXXXতারা পরীক্ষার পদ্ধতি, এবং কেবল সেগুলি কার্যকর করে। তবে এটির পরিবর্তে টীকাগুলি দিয়ে আরও ভাল করা যায় এবং প্রকৃতপক্ষে JUnit 4 মূলত এর পরিবর্তে টীকাগুলিতে স্থানান্তরিত হয়েছে।


6
"আরও শক্তিশালী" যত্ন প্রয়োজন। ট্যুরিং সম্পূর্ণতা পেতে আপনার প্রতিবিম্বের প্রয়োজন নেই, সুতরাং কোনও গণনার প্রতিফলন প্রয়োজন হয় না। অবশ্যই টুরিং সম্পূর্ণরূপে I / O ক্ষমতা এবং অবশ্যই প্রতিফলনের মতো অন্যান্য ধরণের পাওয়ার সম্পর্কে কিছুই বলে না।
স্টিভ 314

1
প্রতিবিম্ব অগত্যা "বেশি ধীর" হয় না। আপনি সরাসরি কলিং র‌্যাপার বাইকোড তৈরি করতে একবার প্রতিবিম্ব ব্যবহার করতে পারেন।
এসকে-যুক্তি

2
আপনার যখন প্রয়োজন হবে তখন আপনি এটি জানতে পারবেন। আমি প্রায়শই ভাবতাম যে কেন (ভাষা প্রজন্মের বাইরে) একজনের এটির প্রয়োজন হবে। তারপরে, হঠাৎ করেই, আমি করেছি ... আমি যখন অন্য রক্ষণাবেক্ষণকারীদের সিস্টেমগুলি রক্ষণ করি তার মধ্যে একটিতে প্যানেল পেতে অন্য ডেভস থেকে প্যানেল পেয়ে ডেটা উঁকি দেওয়ার / পোকার জন্য পিতামাতার / শিশু শৃঙ্খলার উপর দিয়ে হেঁটে যেতে হয়েছিল।
ব্রায়ান নোব্লাচ

@ এসকে-লজিক: আসলে বাইটকোড উত্পন্ন করার জন্য আপনার মোটেও প্রতিবিম্বের প্রয়োজন হবে না (প্রকৃতপক্ষে প্রতিবিম্বে বাইকোড ম্যানিপুলেশনের জন্য কোনও এপিআই নেই!)।
জোচিম সউর

1
@ জোচিমসৌয়ার অবশ্যই, তবে এই উত্পন্ন বাইকোডটি লোড করার জন্য আপনার একটি প্রতিবিম্ব API দরকার হবে ।
এসকে-যুক্তি

15

আমি একবার আপনার মতো ছিলাম, আমি প্রতিবিম্ব সম্পর্কে খুব বেশি জানতাম না - এখনও নেই - তবে আমি এটি একবার ব্যবহার করেছি।

আমার দুটি ক্লাসে দুটি ইন্টার্ন ক্লাস ছিল এবং প্রতিটি ক্লাসে প্রচুর পদ্ধতি ছিল।

আমার অভ্যন্তরীণ শ্রেণীর সমস্ত পদ্ধতির অনুরোধ করা দরকার ছিল এবং তাদের ম্যানুয়ালি আহ্বান করা খুব বেশি কাজ হত।

প্রতিবিম্ব ব্যবহার করে, আমি নিজে পদ্ধতিগুলির সংখ্যার পরিবর্তে কোডের মাত্র ২-৩ টি লাইনে এই সমস্ত পদ্ধতিতে প্রার্থনা করতে পারি।


4
ডাউনটা কেন?
মাহমুদ হোসাম

1
উপস্থাপকের জন্য উত্সাহ দেওয়া
দিমিত্রি মিনকভস্কি

1
@ মাহমুদহসাম সম্ভবত সেরা অনুশীলন নয়, তবে আপনার উত্তরটি একটি গুরুত্বপূর্ণ কৌশলটি প্রয়োগ করতে পারে যা চিত্রিত করে illust
ankush981

13

আমি প্রতিবিম্বের ব্যবহারগুলি তিনটি গ্রুপে গ্রুপ করব:

  1. স্বেচ্ছাসেবীর ক্লাস ইনস্ট্যান্ট করছে। উদাহরণস্বরূপ, একটি নির্ভরতা ইনজেকশন কাঠামোতে আপনি সম্ভবত ঘোষণা করেন যে ইন্টারফেস থিংডোয়ার ক্লাস নেটওয়ার্কটিংডোয়ার দ্বারা প্রয়োগ করা হয়েছে। এর পরে ফ্রেমওয়ার্কটি নেটওয়ার্কিংহিংডোয়ারের নির্মাণকারীর সন্ধান করবে এবং এটি ইনস্ট্যান্ট করবে।
  2. মার্শেলিং এবং অন্য কিছু ফর্ম্যাটে আনমারশেলিং। উদাহরণস্বরূপ, জেটস এবং সেটিংসের সাহায্যে কোনও বস্তুর ম্যাপিং যা শিমের কনভেনশনটিকে JSON এ অনুসরণ করে এবং আবার ফিরে। কোডটি আসলে ক্ষেত্রগুলির নামগুলি বা পদ্ধতিগুলি জানে না, এটি কেবল ক্লাস পরীক্ষা করে।
  3. পুনঃনির্দেশের একটি স্তরে একটি ক্লাস মোড়ানো (সম্ভবত সেই তালিকাটি আসলে লোড করা হয়নি, তবে এটি কেবল ডেটাবেস থেকে আনতে হবে এমন কোনও জিনিসের পয়েন্টার) বা সম্পূর্ণরূপে একটি শ্রেণি নষ্ট করা (জেমক একটি সিন্থেটিক শ্রেণি তৈরি করবে যা একটি ইন্টারফেস প্রয়োগ করে) পরীক্ষার উদ্দেশ্যে)

এটি স্ট্যাকএক্সচেঞ্জের প্রতিবিম্বের সেরা ব্যাখ্যা। বেশিরভাগ উত্তর জাভা ট্রেল যা বলেছে তার পুনরাবৃত্তি করে (যা "আপনি এই সমস্ত বৈশিষ্ট্য অ্যাক্সেস করতে পারেন", তবে আপনি কেন করেন না), প্রতিচ্ছবি এমন কিছু করার উদাহরণ প্রদান করেন যা না করা আরও সহজ, বা কীভাবে বসন্ত সম্পর্কে কিছুটা অস্পষ্ট উত্তর দেয় এটি ব্যবহার করে। এই উত্তরটি আসলে তিনটি বৈধ উদাহরণ দেয় যা সহজেই JVM দ্বারা প্রতিবিম্ব ছাড়াই কাজ করতে পারে না। ধন্যবাদ!
এনডিএম 13

3

প্রতিচ্ছবি এমন কোনও প্রোগ্রামকে কোড সহ কাজ করার অনুমতি দেয় যা উপস্থিত নাও হতে পারে এবং এটি নির্ভরযোগ্য উপায়ে করতে পারে।

"নরমাল কোড" এর স্নিপেটস রয়েছে URLConnection c = nullযা এর নিরূপণ উপস্থিতিতে ক্লাস লোডারকে এই ক্লাসটি লোড করার অংশ হিসাবে একটি ইউআরএল সংযোগ শ্রেণি লোড করে, একটি ক্লাসনটফাউন্ড ব্যতিক্রম ছুঁড়ে ফেলে এবং প্রস্থান করে।

প্রতিবিম্ব আপনাকে স্ট্রিং আকারে তাদের নামের উপর ভিত্তি করে ক্লাসগুলি লোড করতে দেয় এবং তাদের উপর নির্ভরশীল প্রকৃত ক্লাস শুরু করার আগে বিভিন্ন সম্পত্তি (আপনার নিয়ন্ত্রণের বাইরে একাধিক সংস্করণের জন্য দরকারী) জন্য তাদের পরীক্ষা করতে দেয়। একটি সাধারণ উদাহরণ হল ওএস এক্স নির্দিষ্ট কোড যা জাভা প্রোগ্রামগুলিকে ওএস এক্স এর অধীনে স্থানীয় দেখানোর জন্য ব্যবহৃত হয় যা অন্যান্য প্ল্যাটফর্মগুলিতে উপস্থিত নেই।


2

মৌলিকভাবে, প্রতিবিম্ব মানে আপনার প্রোগ্রামের কোডটিকে ডেটা হিসাবে ব্যবহার করা।

সুতরাং, যখন আপনার প্রোগ্রামের কোড ডেটা ব্যবহারের উত্স হয় তখন প্রতিবিম্বটি ব্যবহার করা ভাল ধারণা হতে পারে। (তবে ট্রেড অফ রয়েছে তাই এটি সর্বদা ভাল ধারণা নাও থাকতে পারে))

উদাহরণস্বরূপ, একটি সাধারণ শ্রেণি বিবেচনা করুন:

public class Foo {
  public int value;
  public string anotherValue;
}

এবং আপনি এটি থেকে এক্সএমএল তৈরি করতে চান। আপনি এক্সএমএল তৈরি করতে কোড লিখতে পারেন:

public XmlNode generateXml(Foo foo) {
  XmlElement root = new XmlElement("Foo");
  XmlElement valueElement = new XmlElement("value");
  valueElement.add(new XmlText(Integer.toString(foo.value)));
  root.add(valueElement);
  XmlElement anotherValueElement = new XmlElement("anotherValue");
  anotherValueElement.add(new XmlText(foo.anotherValue));
  root.add(anotherValueElement);
  return root;
}

তবে এটি অনেকগুলি বয়লারপ্লেট কোড এবং আপনি যখনই ক্লাস পরিবর্তন করেন তখন আপনাকে কোডটি আপডেট করতে হয়। সত্যিই, আপনি এই কোডটি কী করে তা বর্ণনা করতে পারেন

  • শ্রেণীর নাম সহ একটি এক্সএমএল উপাদান তৈরি করুন
  • শ্রেণীর প্রতিটি সম্পত্তি জন্য
    • সম্পত্তির নাম সহ একটি এক্সএমএল উপাদান তৈরি করুন
    • এক্সএমএল উপাদানটির মধ্যে সম্পত্তিটির মান রাখুন
    • মূলটিতে এক্সএমএল উপাদান যুক্ত করুন

এটি একটি অ্যালগরিদম, এবং অ্যালগরিদমের ইনপুটটি বর্গ: আমাদের এটির নাম এবং এর বৈশিষ্ট্যগুলির নাম, প্রকার এবং মান প্রয়োজন। এখানেই প্রতিচ্ছবি আসে: এটি আপনাকে এই তথ্যে অ্যাক্সেস দেয়। জাভা আপনাকে এর পদ্ধতি ব্যবহার করে প্রকারের পরীক্ষা করতে দেয় toClass ক্লাসের ।

আরও কিছু ব্যবহারের ক্ষেত্রে:

  • কোনও ক্লাসের পদ্ধতির নামের উপর ভিত্তি করে URL এবং ওয়েব আর্গুমেন্টের ভিত্তিতে ইউআরএল প্যারামিটারের ভিত্তিতে একটি URL টি সংজ্ঞায়িত করুন
  • শ্রেণীর কাঠামোটিকে গ্রাফিক্যুয়াল টাইপ সংজ্ঞায় রূপান্তর করুন
  • শ্রেণীর প্রতিটি পদ্ধতিতে কল করুন যার নামটি ইউনিট পরীক্ষার কেস হিসাবে "পরীক্ষা" দিয়ে শুরু হয়

যাইহোক, পূর্ণ প্রতিবিম্বের অর্থ কেবল বিদ্যমান কোডের দিকে তাকানোই নয় (যা নিজে থেকেই "অন্তঃক্ষেত্র" হিসাবে পরিচিত is), কোড সংশোধন বা জেনারেট করে। জাভাতে এর জন্য দুটি প্রধান ব্যবহারের মামলা রয়েছে: প্রক্সি এবং উপহাস ocks

ধরা যাক আপনার একটি ইন্টারফেস রয়েছে:

public interface Froobnicator {
  void froobnicateFruits(List<Fruit> fruits);
  void froobnicateFuel(Fuel fuel);
  // lots of other things to froobnicate
}

এবং আপনার একটি বাস্তবায়ন রয়েছে যা আকর্ষণীয় কিছু করে:

public class PowerFroobnicator implements Froobnicator {
  // awesome implementations
}

এবং বাস্তবে আপনার একটি দ্বিতীয় বাস্তবায়নও রয়েছে:

public class EnergySaverFroobnicator implements Froobnicator {
  // efficient implementations
}

এখন আপনি কিছু লগ আউটপুট চান; যখনই কোনও পদ্ধতি বলা হয় আপনি কেবল লগ বার্তা চান want আপনি প্রতিটি পদ্ধতিতে স্পষ্টভাবে লগ আউটপুট যুক্ত করতে পারেন, তবে এটি বিরক্তিকর হবে, এবং আপনাকে এটি দুটিবার করতে হবে; প্রতিটি বাস্তবায়নের জন্য একবার। (সুতরাং আপনি আরও বাস্তবায়ন যোগ করার সময় আরও বেশি।)

পরিবর্তে, আপনি একটি প্রক্সি লিখতে পারেন:

public class LoggingFroobnicator implements Froobnicator {
  private Logger logger;
  private Froobnicator inner;

  // constructor that sets those two

  public void froobnicateFruits(List<Fruit> fruits) {
    logger.logDebug("froobnicateFruits called");
    inner.froobnicateFruits(fruits);
  }

  public void froobnicateFuel(Fuel fuel) {
    logger.logDebug("froobnicateFuel( called");
    inner.froobnicateFuel(fuel);
  }
  // lots of other things to froobnicate
}

আবার, যদিও, একটি পুনরাবৃত্তি প্যাটার্ন রয়েছে যা একটি অ্যালগরিদম দ্বারা বর্ণনা করা যেতে পারে:

  • লগার প্রক্সি এমন একটি শ্রেণি যা একটি ইন্টারফেস প্রয়োগ করে
  • এটিতে এমন একটি কনস্ট্রাক্টর রয়েছে যা ইন্টারফেসের একটি অন্য বাস্তবায়ন গ্রহণ করে এবং একটি লগার
  • ইন্টারফেসের প্রতিটি পদ্ধতির জন্য
    • বাস্তবায়ন একটি বার্তা "$ পদ্ধতি নাম" লগ করে
    • এবং তারপরে সমস্ত আর্গুমেন্টের পাশ দিয়ে অভ্যন্তরীণ ইন্টারফেসে একই পদ্ধতিটিকে কল করে

এবং এই অ্যালগরিদমের ইনপুট হ'ল ইন্টারফেস সংজ্ঞা।

প্রতিচ্ছবি আপনাকে এই অ্যালগরিদম ব্যবহার করে একটি নতুন শ্রেণি সংজ্ঞায়িত করতে দেয়। জাভা আপনাকে java.lang.reflect.Proxyক্লাসের পদ্ধতিগুলি ব্যবহার করে এটি করার অনুমতি দেয় এবং এমন গ্রন্থাগার রয়েছে যা আপনাকে আরও বেশি শক্তি দেয়।

তাহলে প্রতিবিম্বের ডাউনসাইট কী কী?

  • আপনার কোডটি বোঝা শক্ত হয়ে যায়। আপনার বিধিবিধানের এক স্তর আপনার কোডের কংক্রিট প্রভাব থেকে আরও সরানো হয়েছে।
  • আপনার কোডটি ডিবাগ করা শক্ত হয়ে যায়। বিশেষত কোড উত্পন্ন গ্রন্থাগারগুলির সাথে, কার্যকর করা কোডটি আপনার লেখা কোডটি নাও হতে পারে তবে আপনি যে কোডটি উত্পন্ন করেছেন এবং ডিবাগারটি আপনাকে সেই কোডটি প্রদর্শন করতে সক্ষম হতে পারে না (বা আপনাকে ব্রেকপয়েন্টগুলি রাখতে দেয়)।
  • আপনার কোডটি ধীর হয়ে যায়। গতিশীলভাবে ধরণের তথ্য পড়ুন এবং হার্ড-কোডিং অ্যাক্সেসের পরিবর্তে রানটাইম হ্যান্ডেলগুলি দ্বারা ক্ষেত্রগুলিতে অ্যাক্সেস করা ধীর হয় is ডায়নামিক কোড জেনারেশন এই প্রভাবটি হ্রাস করতে পারে, ডিবাগ করা এমনকি আরও শক্ত হওয়ার জন্য।
  • আপনার কোডটি আরও ভঙ্গুর হতে পারে। গতিশীল প্রতিচ্ছবি অ্যাক্সেস সংকলক দ্বারা টাইপ-চেক করা হয় না, রানটাইম সময় ত্রুটি নিক্ষেপ।

1

প্রতিবিম্ব স্বয়ংক্রিয়ভাবে আপনার প্রোগ্রামের কিছু অংশ সিঙ্কে রাখতে পারে, যেখানে আগে আপনাকে নতুন ইন্টারফেসগুলি ব্যবহার করতে নিজের প্রোগ্রামটি ম্যানুয়ালি আপডেট করতে হত।


5
এই ক্ষেত্রে আপনি যে মূল্য প্রদান করবেন তা হ'ল আপনি আইডিইতে সংকলক এবং রিফ্যাক্টর-সুরক্ষা দ্বারা টাইপ-চেকিং হারাবেন। এটি এমন বাণিজ্য যা আমি তৈরি করতে রাজি নই।
বেরেন্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.