PECS (প্রযোজক গ্রাহক সুপার প্রসারিত) কী?


727

জেনেরিকগুলি পড়তে গিয়ে আমি PECS জুড়ে এসেছি ( প্রযোজক extendsএবং ভোক্তারsuper পক্ষে সংক্ষিপ্ত )।

কেউ মধ্যে সমাধান বিভ্রান্তির pecs কীভাবে ব্যবহার করবেন তা আমাকে ব্যাখ্যা করতে পারবেন extendsএবং super?


3
@ Youtube.com/watch?v=34oiEq9nD0M&feature=youtu.be&t=1630 উদাহরণ সহ একটি খুব ভাল ব্যাখ্যা যা superঅংশটি ব্যাখ্যা করে তবে, অন্যটির ধারণা দেয়।
lupchiazoem

উত্তর:


840

tl; dr: "PECS" সংগ্রহের দৃষ্টিকোণ থেকে। আপনি যদি জেনেরিক সংগ্রহ থেকে কেবল আইটেমগুলি টানছেন তবে এটি নির্মাতা এবং আপনার ব্যবহার করা উচিত extends; আপনি যদি কেবল আইটেমগুলিতে স্টাফ করে থাকেন তবে এটি গ্রাহক এবং আপনার ব্যবহার করা উচিত super। যদি আপনি একই সংগ্রহের মাধ্যমে উভয়টি করেন তবে আপনার উচিত হয় না extendsবা ব্যবহার করা উচিত super


ধরুন আপনার কাছে এমন একটি পদ্ধতি রয়েছে যা এর পরামিতি হিসাবে জিনিসগুলির সংগ্রহ হিসাবে গ্রহণ করে তবে আপনি এটি কেবল একটি গ্রহণের চেয়ে আরও নমনীয় হতে চান Collection<Thing>

কেস 1: আপনি সংগ্রহের মাধ্যমে যেতে এবং প্রতিটি আইটেম দিয়ে জিনিস করতে চান want
তারপরে তালিকাটি একজন প্রযোজক , সুতরাং আপনার ব্যবহার করা উচিত Collection<? extends Thing>

যুক্তিটি হ'ল যে Collection<? extends Thing>কোনওর কোনও উপ-টাইপ ধরে রাখতে পারে Thingএবং এভাবে Thingআপনি যখন নিজের ক্রিয়াকলাপ সম্পাদন করেন তখন প্রতিটি উপাদান একটি হিসাবে আচরণ করবে । (আপনি আসলে একটিতে কিছু যুক্ত করতে পারবেন না Collection<? extends Thing>, কারণ সংগ্রহের নির্দিষ্ট উপ-প্রকারটি রানটাইমটিতে আপনি জানতে পারবেন না Thing))

কেস 2: আপনি সংগ্রহে জিনিসগুলি যুক্ত করতে চান।
তারপরে তালিকাটি ভোক্তা , সুতরাং আপনার ব্যবহার করা উচিত Collection<? super Thing>

যুক্তি এখানে অসদৃশ হয় Collection<? extends Thing>, Collection<? super Thing>সবসময় একটি ধরে রাখতে পারেন Thingকোন ব্যাপার কি প্রকৃত স্থিতিমাপ প্রকার। এখানে আপনি যতক্ষণ না তালিকায় ইতিমধ্যে যা রয়েছেন যতক্ষণ এটি Thingযুক্ত হওয়ার অনুমতি দেয়; এটিই ? super Thingগ্যারান্টি দেয়।


142
আমি সবসময় এটা সম্পর্কে এই ভাবে চিন্তা করার চেষ্টা করছি: একটি প্রযোজক কিছু উত্পাদন আরও নির্দিষ্ট করার অনুমতি দেওয়া হয়, অত: পর প্রসারিত , একটি ভোক্তা , আরও সাধারণ কিছু গ্রহণ করতে অনুমতি দেওয়া হয় অত: পর সুপার
ফিউমুরমেল

10
উত্পাদক / গ্রাহক পার্থক্য মনে রাখার আরেকটি উপায় হল কোনও পদ্ধতির স্বাক্ষরের কথা চিন্তা করা। আপনি যদি একটি পদ্ধতি থাকে তাহলে doSomethingWithList(List list), আপনি হয় গ্রাসকারী তালিকা এবং তাই সহভেদাংক প্রয়োজন হবে / প্রসারিত (অথবা একটি পরিবর্তিত তালিকা)। অন্যদিকে আপনার পদ্ধতিটি যদি হয় List doSomethingProvidingListতবে আপনি তালিকাটি তৈরি করছেন এবং এর জন্য বিপরীত / সুপার (বা একটি আক্রমণকারী তালিকা) প্রয়োজন হবে।
রমন

3
@ মিশেলমায়ারস: কেন আমরা কেবলমাত্র এই উভয় ক্ষেত্রেই প্যারামিটারাইজড টাইপ ব্যবহার করতে পারি না? এখানে ওয়াইল্ডকার্ড ব্যবহারের কোনও সুনির্দিষ্ট সুবিধা রয়েছে কি না const, এটি পদ্ধতিটি আর্গুমেন্টগুলিকে সংশোধন করে না তা বোঝাতে সি ++ তে পদ্ধতি পরামিতি হিসাবে উল্লেখগুলি ব্যবহার করার মতোই বলার মতো পঠনযোগ্যতা উন্নত করার একটি মাধ্যম ?
চ্যাটার্জি

7
@ রমন, আমি মনে করি আপনি এটি ঠিক বিভ্রান্ত করেছেন। DoSthWithList- এ (আপনার তালিকা <? সুপার থিং> থাকতে পারে), যেহেতু আপনি একজন গ্রাহক, আপনি সুপার ব্যবহার করতে পারেন (মনে রাখবেন, সিএস)। তবে, এটি তালিকা <? থিং> গেটলিস্ট () প্রসারিত করে যেহেতু আপনাকে উত্পাদন করার সময় আরও নির্দিষ্ট কিছু ফেরত দেওয়ার অনুমতি দেওয়া হয়।
মাস্টারেক্সিলো

4
@ এজেড_ আমি আপনার অনুভূতি শেয়ার করছি যদি কোনও পদ্ধতি তালিকা থেকে () পায় তবে পদ্ধতিটি গ্রাহক <টি> হিসাবে বিবেচিত হবে এবং তালিকাটি সরবরাহকারী হিসাবে বিবেচিত হবে; তবে পিইসিএসের বিধিটি "তালিকার দৃষ্টিকোণ থেকে", সুতরাং 'প্রসারিত' বলা হয় called এটি জিইপিএস হওয়া উচিত: প্রসারিত হওয়া; সুপার রাখা।
ট্রিফিশ ঝাং

561

কম্পিউটার বিজ্ঞানে এর পিছনের নীতিগুলি বলা হয়

  • সহভেদাংক: ? extends MyClass,
  • বৈপরীত্য: ? super MyClassএবং
  • Invariance / অ ভ্যারিয়েন্স: MyClass

নীচের ছবিতে ধারণাটি ব্যাখ্যা করা উচিত। ছবি সৌজন্যে: আন্দ্রে টিউকিন

কোভারিয়েন্স বনাম কনট্রাভারিয়েন্স


143
হেই সবাই. আমি আন্ড্রে টিউকিন, আমি কেবল এটি নিশ্চিত করতে চেয়েছিলাম যে অ্যানোপেলিয়াস এবং দাওওয়েইন আমার সাথে যোগাযোগ করেছিলেন এবং স্কেচটি ব্যবহারের জন্য আমার অনুমতি পেয়েছেন, এটি (সিসি) -বিওয়াই-এসএ এর আওতায় লাইসেন্সপ্রাপ্ত। Thx @ আনুপকে এটিকে দ্বিতীয় জীবন দেওয়ার জন্য ^^ @ ব্রায়ান অগ্নিউ: ("কয়েকটি ভোটে"): এটি স্কালার জন্য একটি স্কেচ বলে, এটি স্কালা সিনট্যাক্স ব্যবহার করে এবং ডিক্লারেশন-সাইটের ভেরিয়েন্স ধরে নেয়, যা জাভার অদ্ভুত কলটির থেকে একেবারেই আলাদা -সাইটের ভেরিয়েন্স ... সম্ভবত আমার আরও বিস্তারিত উত্তর লেখা উচিত যা স্পষ্টভাবে দেখায় যে এই স্কেচটি জাভাতে কীভাবে প্রযোজ্য ...
আন্দ্রে ট্যুকিন

3
এটি কোভারিয়েন্স এবং কন্ট্রোভারিয়েন্সের জন্য আমি সবচেয়ে সহজ এবং স্পষ্ট ব্যাখ্যা যা খুঁজে পেয়েছি!
cs4r

@ আন্দ্রে টিউকিন হাই, আমিও এই চিত্রটি ব্যবহার করতে চাই। কিভাবে আপনার সাথে যোগাযোগ করতে পারি?
slouc

এই দৃষ্টান্তটি সম্পর্কে আপনার যদি কোনও প্রশ্ন থাকে তবে আমরা তাদের সাথে চ্যাটরুমে আলোচনা করতে পারি: chat.stackoverflow.com/rooms/145734/…
আন্দ্রে ট্যুকিন


48

পিসিএস (প্রযোজক extendsএবং গ্রাহক super)

স্মৃতিচারণ → নীতিটি পান এবং রাখুন।

এই নীতিটি বলে যে:

  • আপনি যখন কেবল কোনও কাঠামোর বাইরে মান পাবেন তখন একটি প্রসারিত ওয়াইল্ডকার্ড ব্যবহার করুন।
  • আপনি যখন কেবল কাঠামোর মধ্যে মান রাখেন তখন একটি সুপার ওয়াইল্ডকার্ড ব্যবহার করুন।
  • যখন আপনি দুজনেই পেয়ে যাবেন তখন কোনও ওয়াইল্ডকার্ড ব্যবহার করবেন না।

জাভা উদাহরণ:

class Super {

    Object testCoVariance(){ return null;} //Covariance of return types in the subtype.
    void testContraVariance(Object parameter){} // Contravariance of method arguments in the subtype.
}

class Sub extends Super {

    @Override
    String testCoVariance(){ return null;} //compiles successfully i.e. return type is don't care(String is subtype of Object) 
    @Override
    void testContraVariance(String parameter){} //doesn't support even though String is subtype of Object

}

লিসকোভ প্রতিস্থাপনের নীতি: যদি এস টি টির একটি উপপ্রকার হয়, তবে টি টাইপের বস্তুগুলিকে এস টাইপের বস্তুর সাথে প্রতিস্থাপন করা যেতে পারে Lis

প্রোগ্রামিং ভাষার টাইপ সিস্টেমের মধ্যে, একটি টাইপিংয়ের নিয়ম

  • কোভারিয়েন্ট যদি এটি প্রকারের ক্রম সংরক্ষণ করে (≤), যা আরও নির্দিষ্ট থেকে আরও জেনেরিকের জন্য প্রকারকে অর্ডার করে;
  • বিতর্কিত যদি এটি এই ক্রমটিকে বিপরীত করে;
  • পরিবর্তিত বা nonvariant যদি এই তন্ন তন্ন প্রযোজ্য।

সমবায়তা এবং বৈপরীত্য

  • কেবল পঠনযোগ্য ডেটা প্রকার (উত্স) সমবায় হতে পারে ;
  • কেবল লেখার জন্য ডেটা টাইপ (ডুবে) বিপরীত হতে পারে ।
  • চপল ধরনের তথ্য যা উভয় সূত্র ও কুন্ড হিসাবে কাজ হওয়া উচিত পরিবর্তিত

এই সাধারণ ঘটনাটি চিত্রিত করতে অ্যারের ধরণটি বিবেচনা করুন। প্রকারের প্রকারের জন্য আমরা প্রকারের প্রাণীটি তৈরি করতে পারি []

  • কোভেরিয়েন্ট : একটি বিড়াল [] একটি প্রাণী [];
  • বিপরীতমুখী : একটি প্রাণী [] একটি বিড়াল [];
  • আক্রমণকারী : একটি প্রাণী [] একটি বিড়াল নয় [] এবং একটি বিড়াল [] একটি প্রাণী নয় []।

জাভা উদাহরণ:

Object name= new String("prem"); //works
List<Number> numbers = new ArrayList<Integer>();//gets compile time error

Integer[] myInts = {1,2,3,4};
Number[] myNumber = myInts;
myNumber[0] = 3.14; //attempt of heap pollution i.e. at runtime gets java.lang.ArrayStoreException: java.lang.Double(we can fool compiler but not run-time)

List<String> list=new ArrayList<>();
list.add("prem");
List<Object> listObject=list; //Type mismatch: cannot convert from List<String> to List<Object> at Compiletime  

আরও উদাহরণ

সীমাবদ্ধ (অর্থাত্ কোথাও যাচ্ছেন) ওয়াইল্ডকার্ড : ওয়াইল্ডকার্ডের 3 টি আলাদা স্বাদ রয়েছে:

  • ইন-ভেরিয়েন্স / নন-ভেরিয়েন্স: ?বা ? extends Object- আনবাউন্ডেড ওয়াইল্ডকার্ড। এটি সকল প্রকারের পরিবারকে বোঝায়। আপনি উভয় পেতে এবং রাখা যখন ব্যবহার করুন।
  • সহ-প্রকরণ: ? extends T(সমস্ত ধরণের উপপরিবারের পরিবার T) - উপরের সীমা সহ একটি ওয়াইল্ডকার্ড । Tহয় উপরের উত্তরাধিকার শ্রেণীবিন্যাসে -most বর্গ। extendsযখন আপনি কেবল কাঠামোর বাইরে মান পান তখন একটি ওয়াইল্ডকার্ড ব্যবহার করুন ।
  • কনট্রা-ভেরিয়েন্স: ? super T(সমস্ত ধরণের পরিবার যা সুপারটাইপস T)) - নীচের দিকে আবদ্ধ একটি ওয়াইল্ডকার্ড । Tহয় নিম্ন উত্তরাধিকার শ্রেণীবিন্যাসে -most বর্গ। একটি ব্যবহার করুন superওয়াইল্ডকার্ড যখন আপনি শুধুমাত্র রাখুন একটি গঠন মধ্যে মান।

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

এখানে চিত্র বর্ণনা লিখুন

class Shape { void draw() {}}

class Circle extends Shape {void draw() {}}

class Square extends Shape {void draw() {}}

class Rectangle extends Shape {void draw() {}}

public class Test {
 /*
   * Example for an upper bound wildcard (Get values i.e Producer `extends`)
   * 
   * */  

    public void testCoVariance(List<? extends Shape> list) {
        list.add(new Shape()); // Error:  is not applicable for the arguments (Shape) i.e. inheritance is not supporting
        list.add(new Circle()); // Error:  is not applicable for the arguments (Circle) i.e. inheritance is not supporting
        list.add(new Square()); // Error:  is not applicable for the arguments (Square) i.e. inheritance is not supporting
        list.add(new Rectangle()); // Error:  is not applicable for the arguments (Rectangle) i.e. inheritance is not supporting
        Shape shape= list.get(0);//compiles so list act as produces only

        /*You can't add a Shape,Circle,Square,Rectangle to a List<? extends Shape> 
         * You can get an object and know that it will be an Shape
         */         
    }
      /* 
* Example for  a lower bound wildcard (Put values i.e Consumer`super`)
* */
    public void testContraVariance(List<? super Shape> list) {
        list.add(new Shape());//compiles i.e. inheritance is supporting
        list.add(new Circle());//compiles i.e. inheritance is  supporting
        list.add(new Square());//compiles i.e. inheritance is supporting
        list.add(new Rectangle());//compiles i.e. inheritance is supporting
        Shape shape= list.get(0); // Error: Type mismatch, so list acts only as consumer
        Object object= list.get(0); // gets an object, but we don't know what kind of Object it is.

        /*You can add a Shape,Circle,Square,Rectangle to a List<? super Shape> 
        * You can't get an Shape(but can get Object) and don't know what kind of Shape it is.
        */  
    }
}

জেনেরিক এবং উদাহরণ


আরে, আমি কেবল শেষ বিচারবুদ্ধির সাথে আপনি কী বোঝাতে চেয়েছিলেন তা জানতে চেয়েছিলেন: "আপনি যদি আমার উপমাটি ভুল বলে মনে করেন তবে আপডেট করুন"। আপনার অর্থ কি যদি এটি নৈতিকভাবে ভুল হয় (যা বিষয়গত) বা প্রোগ্রামিংয়ের প্রসঙ্গে এটি ভুল হয় (যা উদ্দেশ্যমূলক: না, এটি ভুল নয়)? আমি এটিকে আরও নিরপেক্ষ উদাহরণ দিয়ে প্রতিস্থাপন করতে চাই যা সাংস্কৃতিক রীতিনীতি ও নৈতিক বিশ্বাসের তুলনায় সর্বজনীনভাবে গ্রহণযোগ্য; যদি তা আপনার সাথে ঠিক থাকে।
নিউরন

শেষ পর্যন্ত আমি এটি পেতে পারে। সুন্দর ব্যাখ্যা।
ওলেগ কুটস

2
@ প্রমরাজ,, In-variance/Non-variance: ? or ? extends Object - Unbounded Wildcard. It stands for the family of all types. Use when you both get and put.আমি << > বা তালিকা <তালিকায় উপাদান যুক্ত করতে পারি না? অবজেক্ট> প্রসারিত করে, তাই কেন এটি হতে পারে তা আমি বুঝতে পারি না Use when you both get and put
লিউয়েনবিন_না

1
@LiuWenbin_NO। - উত্তরের সেই অংশটি বিভ্রান্তিমূলক। ?- "আনবাউন্ডেড ওয়াইল্ডকার্ড" - আগ্রাসনের ঠিক বিপরীত সাথে মিলিত হয়। দয়া করে নিম্নলিখিত ডকুমেন্টেশনগুলি দেখুন: docs.oracle.com/javase/tutorial/java/generics/… যা উল্লেখ করে: যে ক্ষেত্রে কোডটি "ইন" এবং "আউট" ভেরিয়েবল উভয় হিসাবে ভেরিয়েবল অ্যাক্সেস করতে হবে, সেখানে করুন ওয়াইল্ডকার্ড ব্যবহার করবেন না (তারা "get" এবং "পুট" এর সমার্থক হিসাবে "ইন" এবং "আউট" ব্যবহার করছে)। বাদে nullআপনি প্যারামিটারাইজড কালেকশনটিতে যোগ করতে পারবেন না ?
মাউসলেব

29
public class Test {

    public class A {}

    public class B extends A {}

    public class C extends B {}

    public void testCoVariance(List<? extends B> myBlist) {
        B b = new B();
        C c = new C();
        myBlist.add(b); // does not compile
        myBlist.add(c); // does not compile
        A a = myBlist.get(0); 
    }

    public void testContraVariance(List<? super B> myBlist) {
        B b = new B();
        C c = new C();
        myBlist.add(b);
        myBlist.add(c);
        A a = myBlist.get(0); // does not compile
    }
}

সুতরাং "? বি" কে "? বি প্রসারিত" হিসাবে ব্যাখ্যা করা উচিত? এটি এমন কিছু যা বি প্রসারিত করে যাতে বি এর সমস্ত সুপার ক্লাস অবজেক্ট পর্যন্ত অন্তর্ভুক্ত থাকে, খ কে বাদ দিয়ে। কোডের জন্য ধন্যবাদ!
সৌরভ পাতিল

3
@SaurabhPatil না, ? extends Bমানে বি এবং কিছু বি ব্যাপ্ত
asgs

24

আমি অন্য প্রশ্নের উত্তরে যেমনটি ব্যাখ্যা করছি , পিইসিএস হ'ল জো রোচ দ্বারা পি রডুসার extends, সি অনসুমারকে মনে রাখতে সহায়তা করার জন্য তৈরি একটি স্মরণীয় যন্ত্র super

এর অর্থ হ'ল যখন কোনও প্যারামিটারাইজড টাইপ কোনও পদ্ধতিতে পাস করা হবে তখন এর উদাহরণ তৈরিT হবে (তারা এটিকে কোনও উপায়ে পুনরুদ্ধার করা হবে), ? extends Tব্যবহার করা উচিত, যেহেতু একটি সাবক্লাসের কোনও উদাহরণও Tএকটি T

যখন কোনও প্যারামিটারাইজড টাইপ কোনও পদ্ধতিতে প্রেরণ করা হয় তখন এর উদাহরণগুলি ব্যবহার করাT হবে (তারা এটি কিছু করার জন্য প্রেরণ করা হবে) ? super Tব্যবহার করা উচিত , কারণ ব্যবহার করা উচিত কারণ একটি Tসুপারিশের কিছু ধরণের গ্রহণযোগ্য পদ্ধতিতে আইনীভাবে কোনও উদাহরণ দেওয়া যেতে পারে T। একটি এ Comparator<Number>ব্যবহার করা যেতে পারে Collection<Integer>, উদাহরণস্বরূপ। ? extends Tকাজ করবে না, কারণ একটি Comparator<Integer>একটিতে কাজ করতে পারে না Collection<Number>

লক্ষ্য করুন সাধারণত আপনি শুধুমাত্র ব্যবহার করা উচিত ? extends Tএবং ? super Tকিছু পদ্ধতির পরামিতি জন্য। পদ্ধতিগুলি কেবল Tজেনেরিক রিটার্ন টাইপের প্যারামিটার হিসাবে ব্যবহার করা উচিত ।


1
এই নীতিটি কি কেবল সংগ্রহের জন্য রয়েছে? যখন এটি একটি তালিকার সাথে সম্পর্কিত করতে চেষ্টা করে তখন তা বোধগম্য হয়। আপনি যদি সাজানোর স্বাক্ষর সম্পর্কে চিন্তা করেন (তালিকা <টি>, তুলনামূলক <? সুপার টি>) ---> এখানে তুলনাকারী সুপারটি ব্যবহার করে তাই এর অর্থ এটি পিসিএস প্রসঙ্গে গ্রাহক। আপনি যখন বাস্তবায়নের উদাহরণ হিসাবে উদাহরণস্বরূপ: জনসাধারণের তুলনা (ব্যক্তি এ, ব্যক্তি খ) a ফেরত a.age <b.age? -1: a.age == বি.এজ? 0: 1; } আমার মনে হয় ব্যক্তি কোনও কিছু গ্রাস করে না তবে বয়স বাড়ায়। এটি আমাকে বিভ্রান্ত করে তোলে। আমার যুক্তিতে কোনও ত্রুটি আছে নাকি পিসিএস কেবল সংগ্রহের জন্য রয়েছে?
ফাতেহ আরসলান

23

সংক্ষেপে, PECS মনে রাখার জন্য তিনটি সহজ নিয়ম:

  1. কোনও সংগ্রহ থেকে আপনার <? extends T>টাইপের অবজেক্ট পুনরুদ্ধার করতে গেলে ওয়াইল্ডকার্ডটি ব্যবহার করুন T
  2. <? super T>যদি আপনার Tকোনও সংগ্রহের মধ্যে ধরণের বিষয়বস্তু লাগানোর প্রয়োজন হয় তবে ওয়াইল্ডকার্ডটি ব্যবহার করুন ।
  3. আপনার যদি উভয় জিনিসই সন্তুষ্ট করতে হয় তবে ভাল, কোনও ওয়াইল্ডকার্ড ব্যবহার করবেন না। এর মত সহজ.

10

আসুন এই শ্রেণিবিন্যাস অনুমান করি:

class Creature{}// X
class Animal extends Creature{}// Y
class Fish extends Animal{}// Z
class Shark extends Fish{}// A
class HammerSkark extends Shark{}// B
class DeadHammerShark extends HammerSkark{}// C

আসুন পিই পরিষ্কার করুন - প্রযোজক প্রসারিত:

List<? extends Shark> sharks = new ArrayList<>();

আপনি কেন এই তালিকায় "শার্ক" প্রসারিত অবজেক্টগুলিকে যুক্ত করতে পারবেন না? মত:

sharks.add(new HammerShark());//will result in compilation error

যেহেতু আপনার একটি তালিকা রয়েছে যা রানটাইমের সময় এ, বি বা সি টাইপের হতে পারে তাই আপনি এতে কোনও এ, বি বা সি টাইপের কোনও বিষয় যুক্ত করতে পারবেন না কারণ আপনি জাভাতে অনুমোদিত নয় এমন সংমিশ্রণটি শেষ করতে পারেন।
অনুশীলনে, সংকলক প্রকৃতপক্ষে সংকলনের সময় দেখতে পাবে যে আপনি একটি বি যুক্ত করেছেন:

sharks.add(new HammerShark());

... তবে রানটাইমে, আপনার বি তালিকা টাইপের একটি সাব টাইপ বা সুপার টাইপ হবে কিনা তা বলার উপায় নেই। রানটাইমের সময় তালিকার ধরণটি এ, বি, সি প্রকারের যে কোনও একটি হতে পারে তাই উদাহরণস্বরূপ আপনি ডেডহ্যামারশার্কের তালিকায় হ্যামারস্কার্ক (সুপার টাইপ) যুক্ত করতে পারবেন না।

* আপনি বলবেন: "ঠিক আছে, তবে কেন এটি ক্ষুদ্রতম হওয়ায় আমি এতে হামারস্কর্ক যুক্ত করতে পারি না?" উত্তরঃ সবচেয়ে ছোট আপনি জানি। তবে হ্যামারস্কার্ক অন্য কারও দ্বারা প্রসারিত হতে পারে এবং আপনি একই দৃশ্যে এসেছেন।

আসুন সিএস পরিষ্কার করুন - গ্রাহক সুপার:

একই শ্রেণিবিন্যাসে আমরা এটি চেষ্টা করতে পারি:

List<? super Shark> sharks = new ArrayList<>();

আপনি কী এবং কেন এই তালিকায় যুক্ত করতে পারেন ?

sharks.add(new Shark());
sharks.add(new DeadHammerShark());
sharks.add(new HammerSkark());

আপনি উপরের ধরণের অবজেক্টগুলিকে যুক্ত করতে পারেন কারণ হাঙ্গর (এ, বি, সি) এর নীচে যে কোনও কিছু সর্বদা হাঙ্গর (এক্স, ওয়াই, জেড) এর উপরে যে কোনও জিনিসের উপপ্রকার হবে। সহজে বোধগম্য.

আপনি শার্কের উপরে প্রকারগুলি যুক্ত করতে পারবেন না , কারণ রানটাইমের সময় যুক্ত ঘোষিত ধরণের তালিকার (এক্স, ওয়াই, জেড) তুলনায় যুক্ত বস্তুর প্রকার হাইয়ারার্কিতে বেশি হতে পারে। এই অনুমতি দেওয়া হয় না.

তবে কেন আপনি এই তালিকা থেকে পড়তে পারবেন না? (আমি আপনাকে বোঝাতে চাইছি আপনি এটি থেকে কোনও উপাদান পেতে পারেন তবে আপনি এটিকে অবজেক্ট ও ব্যতীত অন্য কোনও কিছুতে নির্ধারণ করতে পারবেন না):

Object o;
o = sharks.get(2);// only assignment that works

Animal s;
s = sharks.get(2);//doen't work

রানটাইমের সময় তালিকার ধরণটি এ: এক্স, ওয়াই, জেড, ... এর উপরে যে কোনও প্রকারের হতে পারে ... সংকলকটি আপনার কার্যনির্বাহী বিবৃতিটি সংকলন করতে পারে (যা সঠিক বলে মনে হচ্ছে) তবে রানটাইমগুলিতে (অ্যানিমাল) প্রকারটি কম হতে পারে তালিকার ঘোষিত প্রকারের তুলনায় শ্রেণিবদ্ধতা (যা প্রকৃতি বা এর চেয়ে বেশি হতে পারে)। এই অনুমতি দেওয়া হয় না.

যোগফল

আমরা ব্যবহার <? super T>যোগ করার জন্য ধরনের বস্তু সমান অথবা নীচের Tথেকে Listআমরা এটি থেকে পড়তে পারি না।
আমরা তালিকা থেকে <? extends T>সমান বা নীচের ধরণের অবজেক্টগুলি পড়তে ব্যবহার করি Tআমরা এতে উপাদান যুক্ত করতে পারি না।


9

(একটি উত্তর যুক্ত করা কারণ জেনেরিক্স ওয়াইল্ডকার্ডগুলির সাথে কখনই পর্যাপ্ত উদাহরণ নেই)

       // Source 
       List<Integer> intList = Arrays.asList(1,2,3);
       List<Double> doubleList = Arrays.asList(2.78,3.14);
       List<Number> numList = Arrays.asList(1,2,2.78,3.14,5);

       // Destination
       List<Integer> intList2 = new ArrayList<>();
       List<Double> doublesList2 = new ArrayList<>();
       List<Number> numList2 = new ArrayList<>();

        // Works
        copyElements1(intList,intList2);         // from int to int
        copyElements1(doubleList,doublesList2);  // from double to double


     static <T> void copyElements1(Collection<T> src, Collection<T> dest) {
        for(T n : src){
            dest.add(n);
         }
      }


     // Let's try to copy intList to its supertype
     copyElements1(intList,numList2); // error, method signature just says "T"
                                      // and here the compiler is given 
                                      // two types: Integer and Number, 
                                      // so which one shall it be?

     // PECS to the rescue!
     copyElements2(intList,numList2);  // possible



    // copy Integer (? extends T) to its supertype (Number is super of Integer)
    private static <T> void copyElements2(Collection<? extends T> src, 
                                          Collection<? super T> dest) {
        for(T n : src){
            dest.add(n);
        }
    }

4

এটি আমার কাছে ব্রেস্ট সুপারের প্রসারিত সম্পর্কে সবচেয়ে স্পষ্ট ও সহজতম উপায়:

  • extendsপড়ার জন্য

  • superলেখার জন্য

"প্রযোজক" কে এবং "ভোক্তা" কে সে সম্পর্কিত বিষয়গুলি ভাবার এক অনস্পষ্ট উপায় হিসাবে আমি "পিইসিএস" দেখতে পাই। "Pecs" দৃষ্টিকোণ থেকে সংজ্ঞায়িত করা হয় নিজেই তথ্য সংগ্রহ - সংগ্রহ "হ্রাস" যদি বস্তু লিখিত হচ্ছে থেকে এটা (এটা কলিং কোড থেকে বস্তু গ্রাসকারী হয়), এবং এটি "উত্পাদন করে" যদি অবজেক্ট পড়ুন হচ্ছে থেকে (এটা এটা কিছু কলিং কোডে অবজেক্ট তৈরি করছে)। এটি অন্য যেভাবে নামকরণ করা হয়েছে তার বিপরীতে। স্ট্যান্ডার্ড জাভা এপিআইগুলি কলিং কোডের দৃষ্টিকোণ থেকে নামকরণ করা হয়েছে, সংগ্রহটি নয় not উদাহরণস্বরূপ, java.util.List এর সংগ্রহ কেন্দ্রিক দৃষ্টিভঙ্গির তালিকাটিতে "অ্যাড ()" এর পরিবর্তে "গ্রহন ()" নামে একটি পদ্ধতি থাকা উচিত - সর্বোপরি,উপাদান, কিন্তু তালিকা নিজেই উপাদান গ্রহণ করে।

আমি মনে করি যে সংকলনের সাথে ইন্টারেক্ট করে এমন কোডের দৃষ্টিকোণ থেকে জিনিসগুলি চিন্তা করা আরও স্বজ্ঞাগত, প্রাকৃতিক এবং ধারাবাহিক - কোডটি কি "সংগ্রহ থেকে পাঠানো" বা "লেখার জন্য" সংগ্রহ থেকে সংগ্রহ করে? তারপরে, সংগ্রহে যে কোনও কোড রাইটিং হবে "প্রযোজক" এবং সংগ্রহ থেকে যে কোনও কোড পাঠানো হবে "ভোক্তা"।


আমি যে একই মানসিক সংঘর্ষের মধ্যে চালানো করেছি এবং ছাড়া pecs কোডের নামকরণ লিখুন গণ্ডি নিজেদের নির্দিষ্ট করে না সম্মত ঝোঁক হবে করছে সংগ্রহ ঘোষণা সেট। যতদূর নামকরণের বিষয় হিসাবে আপনার কাছে প্রায়শই সংগ্রহ পছন্দ / উত্পাদনের নাম রয়েছেsrc এবংdst । সুতরাং আপনি একই সাথে কোড এবং পাত্রে উভয়ই একই সাথে কাজ করছেন এবং আমি এই লাইনগুলি বরাবর এটি সম্পর্কে চিন্তাভাবনা শেষ করেছি - "গ্রাহক কোড" একটি উত্পাদনকারী ধারক থেকে গ্রহন করে এবং "উত্পাদনকারী কোড" গ্রাহক পাত্রের জন্য উত্পাদন করে।
মাউসলেবস

4

পিসিএস "বিধি" কেবল নিশ্চিত করে যে নিম্নলিখিতগুলি বৈধ:

  • গ্রাহক: যাই হোক না কেন ?, এটি আইনত উল্লেখ করতে পারে T
  • প্রযোজক: যাই হোক না কেন ?, আইনত এটি দ্বারা উল্লেখ করা যেতে পারে T

লাইন বরাবর আদর্শ জুটি List<? extends T> producer, List<? super T> consumerসহজভাবে নিশ্চিত করা হয় যে সংকলকটি স্ট্যান্ডার্ড "আইএস-এ" উত্তরাধিকার সম্পর্কের নিয়মকে প্রয়োগ করতে পারে। আমরা তাই আইনত কাজ করতে পারে, তাহলে এটা বলতে সহজ হতে পারে <T extends ?>, <? extends T>(বা ভাল Scala এখনো, যেমন আপনি উপরের দেখতে পারেন, এটা [-T], [+T]। দুর্ভাগ্যবশত সেরা আমরা কি করতে পারেন <? super T>, <? extends T>

যখন আমি প্রথম এটির মুখোমুখি হয়েছি এবং এটিকে আমার মাথায় ভেঙে দিয়েছিলাম তবে যান্ত্রিকরাই বুঝতে পেরেছিল তবে কোডটি নিজেই আমার কাছে বিভ্রান্তিকর লাগছিল - আমি ভাবতে থাকি "মনে হচ্ছে" এটির মতো সীমাটি উল্টানোর দরকার নেই "- যদিও আমি উপরোক্ত বিষয়ে স্পষ্ট ছিল - যে এটি কেবল রেফারেন্সের স্ট্যান্ডার্ড নিয়মের সাথে সম্মতি গ্যারান্টি সম্পর্কে about

সাদৃশ্য হিসাবে সাধারণ অ্যাসাইনমেন্টটি ব্যবহার করে আমাকে কী দেখেছে।

নিম্নলিখিত (উত্পাদন প্রস্তুত নয়) খেলনা কোড বিবেচনা করুন:

// copies the elements of 'producer' into 'consumer'
static <T> void copy(List<? extends T> producer, List<? super T> consumer) {
   for(T t : producer)
       consumer.add(t);
}

নিয়োগ উপমা পরিপ্রেক্ষিতে এই ব্যাখ্যা জন্য, হয় রেফারেন্স ওয়াইল্ডকার্ড (অজানা টাইপ) - নিয়োগ এর "বাম দিকে" - এবং নিশ্চিত করে যে যাই হোক না কেন হয়, "-এ আছে" - যেconsumer?<? super T>?T?T এটা নির্ধারিত করা যেতে পারে, কারণ ?একটি সুপার টাইপ (বা বেশিরভাগ ক্ষেত্রে একই ধরণের) T

জন্য producerউদ্বেগ একই এটি শুধু বিপর্যস্ত হল: producer'র ?ওয়াইল্ডকার্ড (অজানা টাইপ) হল প্রসঙ্গ - নিয়োগ এর "ডান দিকে" - এবং <? extends T>নিশ্চিত করে যে যাই হোক না কেন ?হয়, ?"-এ আছে" T- যে এটা নির্ধারিত করা যেতে পারে একটি থেকেT , কারণ ?একটি উপ-ধরন (বা কমপক্ষে একই ধরণের) T


2

এই মনে রাখবেন:

গ্রাহকরা খাওয়ার খাবার (সুপার); প্রযোজক তার পিতামাতার কারখানাটি বাড়িয়ে দেন


1

বাস্তব জীবনের উদাহরণ ব্যবহার করে (কিছু সরলীকরণ সহ):

  1. কোনও তালিকার উপমা হিসাবে ফ্রেইট গাড়ি সহ একটি মালবাহী ট্রেনের কল্পনা করুন।
  2. আপনি করতে পারেন করা যদি পণ্যসম্ভার রয়েছে মালবাহী গাড়িতে পণ্যসম্ভার একই বা ছোট সাইজ মালবাহী গাড়ী চেয়ে =<? super FreightCarSize>
  3. আপনার ডিপোতে পর্যাপ্ত জায়গা (কার্গোর আকারের চেয়ে বেশি) থাকলে আপনি একটি ফ্রেইট গাড়ি থেকে একটি পণ্যসম্ভার আনলোড করতে পারেন =<? extends DepotSize>

1

সহভেদাংক : গ্রহণ উপশাখাকে
Contravariance : supertypes গ্রহণ

কোভেরিয়েন্ট প্রকারগুলি কেবল পঠনযোগ্য, অন্যদিকে বৈষম্যমূলক প্রকারগুলি কেবল লেখার জন্য।

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