কোভেরিয়েন্স, ইনভেরিয়েন্স এবং কনট্রোভারিয়েন্স কী সরল ইংরেজিতে ব্যাখ্যা করা হয়েছে?


113

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

কিন্তু আমি এখনও এই সম্পর্কে ঠিক কি সম্পর্কে একটু বিভ্রান্ত করছি? কেউ কেউ এটি টাইপ এবং সাব টাইপগুলির মধ্যে সম্পর্কের বিষয়ে বলে, কেউ বলে এটি টাইপ রূপান্তর সম্পর্কে এবং কেউ কেউ বলে যে এটি কোনও পদ্ধতিকে ওভাররাইড করা হয়েছে বা অতিরিক্ত বোঝা কিনা তা সিদ্ধান্ত নিতে ব্যবহৃত হয় used

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


দয়া করে এই পোস্টটি দেখুন, এটি আপনার পক্ষে সহায়ক হতে পারে: stackoverflow.com/q/2501023/218717
ফ্রান্সিসকো আলভারাদো

3
সম্ভবত কোনও প্রোগ্রামারের স্ট্যাক এক্সচেঞ্জ টাইপ প্রশ্ন। আপনি যদি সেখানে পোস্ট করেন তবে ঠিক কী বোঝেন তা উল্লেখ করে বিবেচনা করুন এবং কী আপনাকে বিশেষভাবে বিভ্রান্ত করে, কারণ এখনই আপনি কাউকে আপনার জন্য পুরো টিউটোরিয়ালটি আবার লিখতে বলছেন।
ইয়েল

উত্তর:


288

কেউ কেউ বলে এটি এটি টাইপ এবং সাব টাইপগুলির মধ্যে সম্পর্কের বিষয়ে, অন্যরা বলে যে এটি টাইপ রূপান্তর সম্পর্কে এবং অন্যরা বলে যে এটি কোনও পদ্ধতিকে ওভাররাইট করা হয়েছে বা অতিরিক্ত বোঝা কিনা তা সিদ্ধান্ত নিতে এটি ব্যবহৃত হয়।

উপরের সবগুলো.

আন্তরিকভাবে, এই পদগুলি বর্ণনা দেয় যে কীভাবে উপজাতীয় সম্পর্কটি ধরণের রূপান্তর দ্বারা প্রভাবিত হয়। এটি হ'ল, Aএবং Bযদি প্রকারভেদ হয় তবে fএটি একটি ধরণের রূপান্তর, এবং sub উপপ্রকার সম্পর্ক ( A ≤ Bযার অর্থ এটি Aএকটি উপপ্রকার B)

  • fসমবায় হয় যদি A ≤ Bতা বোঝায়f(A) ≤ f(B)
  • fযদি A ≤ Bতা বোঝায় তবে তা বিপরীতf(B) ≤ f(A)
  • f উপরোক্ত দুটি হোল্ড না থাকলে আক্রমণকারী

আসুন একটি উদাহরণ বিবেচনা করা যাক। f(A) = List<A>যেখানে Listঘোষণা করা যাক

class List<T> { ... } 

কি fcovariant, contravariant, অথবা পরিবর্তিত? Covariant অর্থ হবে যে একটি List<String>একটি উপপ্রকার হয় List<Object>, contravariant করে একটি List<Object>একটি উপপ্রকার হয় List<String>এবং পরিবর্তিত যে তন্ন তন্ন অন্যান্য একটি উপপ্রকার, অর্থাত্ List<String>এবং List<Object>অবিনিমেয় ধরনের হয়। জাভাতে, দ্বিতীয়টি সত্য, আমরা বলি (কিছুটা অনানুষ্ঠানিকভাবে) যে জেনেরিকগুলি অবিস্মরণীয়।

আরেকটি উদাহরণ. যাক f(A) = A[]। কি fcovariant, contravariant, অথবা পরিবর্তিত? অর্থাত, স্ট্রিং কি [অবজেক্টের] একটি সাব টাইপ [], অবজেক্ট [] স্ট্রিংয়ের একটি উপপ্রকার [], বা অন্যটির উপপ্রকার নয়? (উত্তর: জাভাতে, অ্যারেগুলি কোভেরিয়েন্ট হয়)

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

x = y;

কেবল তখনই সংকলন করবে typeof(y) ≤ typeof(x)। যে, আমরা ঠিক যে বিবৃতি শিখেছি

ArrayList<String> strings = new ArrayList<Object>();
ArrayList<Object> objects = new ArrayList<String>();

জাভাতে সংকলন করবে না, তবে

Object[] objects = new String[1];

ইচ্ছাশক্তি.

আর একটি উদাহরণ যেখানে সাব-টাইপের সম্পর্কের বিষয়টি হল একটি পদ্ধতির প্রার্থনা অভিব্যক্তি:

result = method(a);

অনানুষ্ঠানিকভাবে বলতে গেলে, এই বিবৃতিটি aপদ্ধতির প্রথম প্যারামিটারের মান নির্ধারণ করে , তারপরে পদ্ধতির মূল অংশটি নির্বাহ করে এবং তারপরে পদ্ধতিগুলিকে মান ফেরত প্রদান করে মূল্যায়ন করা হয় result। শেষ উদাহরণে প্লেইন অ্যাসাইনমেন্টের মতো, "ডান হাতের দিক" অবশ্যই "বাম হাতের" উপ-প্রকারের হতে হবে, অর্থাত্ এই বিবৃতিটি কেবলমাত্র যদি typeof(a) ≤ typeof(parameter(method))ও হয় তবেই বৈধ হতে পারে returntype(method) ≤ typeof(result)। এটি হল, যদি পদ্ধতি দ্বারা ঘোষণা করা হয়:

Number[] method(ArrayList<Number> list) { ... }

নিম্নলিখিত প্রকাশের কোনওটিই সংকলন করবে না:

Integer[] result = method(new ArrayList<Integer>());
Number[] result = method(new ArrayList<Integer>());
Object[] result = method(new ArrayList<Object>());

কিন্তু

Number[] result = method(new ArrayList<Number>());
Object[] result = method(new ArrayList<Number>());

ইচ্ছাশক্তি.

সাবটাইপিংয়ের বিষয়গুলি যেখানে ওভাররাইড হচ্ছে সেখানে অন্য উদাহরণ। বিবেচনা:

Super sup = new Sub();
Number n = sup.method(1);

কোথায়

class Super {
    Number method(Number n) { ... }
}

class Sub extends Super {
    @Override 
    Number method(Number n);
}

অনানুষ্ঠানিকভাবে, রানটাইম এটিকে আবার লিখবে:

class Super {
    Number method(Number n) {
        if (this instanceof Sub) {
            return ((Sub) this).method(n);  // *
        } else {
            ... 
        }
    }
}

চিহ্নিত লাইনটি সংকলনের জন্য, ওভাররাইডিং পদ্ধতির মেথড প্যারামিটার অবশ্যই ওভাররাইড হওয়া পদ্ধতির মেথড প্যারামিটারের একটি সুপারটাইপ হতে হবে এবং রিটার্ন টাইপ ওভাররাইড হওয়া পদ্ধতির একটির একটি উপ-টাইপ হতে হবে। সাধারণভাবে বলতে গেলে, f(A) = parametertype(method asdeclaredin(A))অবশ্যই কমপক্ষে বিপরীত হতে হবে এবং অবশ্যই কমপক্ষে সমবায়ু হতে f(A) = returntype(method asdeclaredin(A))হবে।

উপরের "কমপক্ষে" নোট করুন। সেগুলি ন্যূনতম প্রয়োজনীয়তাগুলি যে কোনও যুক্তিসঙ্গত স্ট্যাটিকালি টাইপ নিরাপদ বস্তু ভিত্তিক প্রোগ্রামিং ভাষা প্রয়োগ করবে, তবে একটি প্রোগ্রামিং ভাষা আরও কঠোর হতে পারে। জাভা ১.৪-এর ক্ষেত্রে, ওভাররাইডিং পদ্ধতিগুলি, অর্থাৎ ওভাররাইড করার সময় প্যারামিটারের ধরণগুলি এবং পদ্ধতির রিটার্নের ধরণগুলি অভিন্ন হতে হবে (টাইপ মুছে ফেলা ব্যতীত) parametertype(method asdeclaredin(A)) = parametertype(method asdeclaredin(B))। জাভা ১.৫ থেকে, ওভাররাইড করার সময় কোভারিয়েন্ট রিটার্নের ধরণের অনুমতি রয়েছে, যেমন নীচে জাভা 1.5 তে সংকলন করা হবে তবে জাভা 1.4 এ নয়:

class Collection {
    Iterator iterator() { ... }
}

class List extends Collection {
    @Override 
    ListIterator iterator() { ... }
}

আমি আশা করি আমি সমস্ত কিছু আবৃত করেছি - বা বরং, পৃষ্ঠটি আঁচড়ান। তবুও আমি আশা করি এটি বিমূর্ত, তবে ধরণের বৈচিত্রের গুরুত্বপূর্ণ ধারণাটি বুঝতে সহায়তা করবে।


1
এছাড়াও, যেহেতু জাভা 1.5 টি বিপরীত যুক্তির প্রকারগুলি ওভাররাইড করার সময় অনুমোদিত। আমি মনে করি আপনি এটি মিস করেছেন।
ব্রায়ান গর্ডন

13
তারা কি? আমি কেবল এটি গ্রহনে চেষ্টা করেছিলাম, এবং সংকলকটি ভেবেছিল যে আমি ওভাররাইডের চেয়ে ওভারলোডের চেয়ে বেশি বোঝাচ্ছি এবং আমি সাবক্লাস পদ্ধতিতে @ ওভাররাইড টীকা দেওয়ার সময় কোডটি প্রত্যাখ্যান করেছি। আপনারা কি দাবি করেছেন যে জাভা বিপরীত যুক্তির প্রকারকে সমর্থন করে?
মেরিটন

1
আহ, আপনি ঠিক বলেছেন। আমি নিজেই এটি পরীক্ষা না করে কাউকে বিশ্বাস করি।
ব্রায়ান গর্ডন

1
আমি প্রচুর ডকুমেন্টেশন পড়েছি এবং এই বিষয়ে কয়েকটি আলোচনা দেখেছি তবে এটি সর্বোত্তম ব্যাখ্যা explanation Thnx অনেক।
minzchickenflavor

1
একেবারে লেমন এবং সাধারণ হওয়ার জন্য +1 A ≤ B। এই স্বরলিপি জিনিসগুলি অনেক বেশি সহজ এবং অর্থবহ করে তোলে। ভাল পড়ুন ...
রোমিও সিয়েরা

12

জাভা টাইপ সিস্টেম নেওয়া, এবং তারপরে ক্লাসগুলি:

কিছু ধরণের টি এর যে কোনও বস্তু টি এর টিউব টাইপের একটি বস্তুর সাথে প্রতিস্থাপিত হতে পারে।

প্রকারের পার্থক্য - শ্রেণিবদ্ধ পদ্ধতিতে নিম্নলিখিত ফলাফলগুলি রয়েছে

class A {
    public S f(U u) { ... }
}

class B extends A {
    @Override
    public T f(V v) { ... }
}

B b = new B();
t = b.f(v);
A a = ...; // Might have type B
s = a.f(u); // and then do V v = u;

এটি দেখা যায়, যে:

  • টি অবশ্যই সাব টাইপ এস ( কোভারিয়েন্ট, যেমন বি এর উপপ্রকার, ) হতে হবে।
  • ভী ইউ এর supertype (আবশ্যক contravariant , বিরূদ্ধে উত্তরাধিকার দিক হিসাবে)।

খ-এর বিপরীতে এবং এ বি এর সাব টাইপ হওয়ার সাথে সম্পর্কিত। নিম্নলিখিত শক্তিশালী টাইপগুলি আরও নির্দিষ্ট জ্ঞানের সাথে প্রবর্তন করা যেতে পারে। সাব টাইপে

কোভারিয়েন্স (জাভাতে উপলভ্য) দরকারী, এটি উপকারের ক্ষেত্রে আরও নির্দিষ্ট ফলাফল প্রত্যাখ্যান করার জন্য; বিশেষত যখন এ = টি এবং বি = এস দেখা যায়। বিপর্যয় বলে যে আপনি আরও সাধারণ যুক্তি পরিচালনা করতে প্রস্তুত।


8

ভেরিয়েন্স বিভিন্ন জেনেরিক পরামিতিগুলির সাথে শ্রেণীর মধ্যে সম্পর্ক সম্পর্কে। তাদের সম্পর্কগুলির কারণেই আমরা এগুলিকে ফেলে দিতে পারি।

কো এবং কনট্রা ভেরিয়েন্স বেশ যুক্তিসঙ্গত জিনিস। ভাষা টাইপ সিস্টেম আমাদের বাস্তব জীবনের যুক্তি সমর্থন করতে বাধ্য করে। উদাহরণ দিয়ে বোঝা সহজ।

সহভেদাংক

উদাহরণস্বরূপ আপনি একটি ফুল কিনতে চান এবং আপনার শহরে আপনার দুটি ফুলের দোকান রয়েছে: গোলাপের দোকান এবং ডেইজি শপ।

আপনি যদি কাউকে জিজ্ঞাসা করেন "ফুলের দোকানটি কোথায়?" এবং কেউ আপনাকে বলবে গোলাপের দোকান কোথায় আছে, ঠিক আছে? হ্যাঁ, কারণ গোলাপ একটি ফুল, আপনি যদি ফুল কিনতে চান তবে আপনি একটি গোলাপ কিনতে পারেন। যদি কেউ আপনাকে ডেইজি শপের ঠিকানা দিয়ে উত্তর দেয় তবে এটি একই প্রযোজ্য। এই উদাহরণ হল সহভেদাংক : আপনি ঢালাই করার অনুমতি দেওয়া হয় A<C>থেকে A<B>, যেখানে Cএকটি উপশ্রেণী হয় B, যদি A(ফাংশন থেকে ফলে আয়) জেনেরিক মান উৎপন্ন হয়। Covariance প্রযোজক সম্পর্কে।

প্রকার:

class Flower {  }
class Rose extends Flower { }
class Daisy extends Flower { }

interface FlowerShop<T extends Flower> {
    T getFlower();
}

class RoseShop implements FlowerShop<Rose> {
    @Override
    public Rose getFlower() {
        return new Rose();
    }
}

class DaisyShop implements FlowerShop<Daisy> {
    @Override
    public Daisy getFlower() {
        return new Daisy();
    }
}

প্রশ্ন "ফুলের দোকানটি কোথায়?", উত্তরটি "গোলাপের দোকান সেখানে":

static FlowerShop<? extends Flower> tellMeShopAddress() {
    return new RoseShop();
}

Contravariance

উদাহরণস্বরূপ আপনি আপনার বান্ধবীকে ফুল উপহার দিতে চান। আপনি যদি গার্লফ্রেন্ড কোনও ফুল পছন্দ করেন তবে আপনি কি তাকে এমন একজন ব্যক্তি হিসাবে বিবেচনা করতে পারেন যা গোলাপকে ভালোবাসে, বা ডাইজি পছন্দ করে এমন ব্যক্তি হিসাবে? হ্যাঁ, কারণ তিনি যদি কোনও ফুল পছন্দ করেন তবে তিনি গোলাপ এবং ডেইজি উভয়কেই পছন্দ করবেন। এটি বিপরীতের একটি উদাহরণ : জেনেরিক মানটি গ্রহণ করলে A<B>আপনাকে A<C>সেখানে, যেখানে Cসাবক্লাস রয়েছে সেখানে নিক্ষেপ করার অনুমতি দেওয়া হবে । বৈপরীত্য গ্রাহকদের সম্পর্কে।BA

প্রকার:

interface PrettyGirl<TFavouriteFlower extends Flower> {
    void takeGift(TFavouriteFlower flower);
}

class AnyFlowerLover implements PrettyGirl<Flower> {
    @Override
    public void takeGift(Flower flower) {
        System.out.println("I like all flowers!");
    }

}

আপনি আপনার গার্লফ্রেন্ডকে বিবেচনা করছেন যিনি যে কোনও ফুলকে গোলাপ ভালবাসেন এবং তাকে একটি গোলাপ উপহার হিসাবে ভালবাসেন:

PrettyGirl<? super Rose> girlfriend = new AnyFlowerLover();
girlfriend.takeGift(new Rose());

আপনি উত্স এ আরও জানতে পারেন ।


@ পিটার, ধন্যবাদ, এটি একটি ন্যায্য বিষয়। বিভিন্ন জেনেরিক প্যারামিটার সহ ক্লাসগুলির মধ্যে কোনও সম্পর্ক না থাকাতে ইন্ভার্ভিয়েন্স হ'ল আপনি বি এবং সি এর মধ্যে যে সম্পর্কই থাকুন না কেন A <B> থেকে A <C> এ কাস্ট করতে পারবেন না।
ভাদজিমভি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.