Kovariacija, invariancija ir kontracepcija yra paaiškinta paprastu anglų kalba?

Šiandien aš perskaičiau keletą straipsnių apie kovariaciją, kontracepciją (ir invarianciją) Java. Aš perskaičiau anglų ir vokiečių Vikipedijos straipsnius, taip pat kai kuriuos kitus dienoraščius ir straipsnius iš IBM.

Bet ar aš vis dar truputį sumišęs apie tai, kas tai yra? Kai kurie kalba apie tipų ir potipių santykį, kai kurie kalbėjo apie tipo konversiją, o kai kurie sako, ką jis nusprendė nuspręsti, ar šis metodas yra viršesnis ar perkrautas.

Taigi, aš ieškau paprasto paaiškinimo paprastu anglų kalba, kuriame rodomi naujokai, kas yra kovariacija ir kontrakcija (ir invariancija). Plius - paprastas pavyzdys.

75
13 дек. nustatyti anon. 13 d. 2011-12-13 00:44 '11 12:44 2011-12-13 00:44
@ 2 atsakymai

Kai kurie sako, kad tai susiję su tipų ir potipių santykiu, kiti sako, kad tai tipo konvertavimas, o kiti sako, kad jis naudojamas nustatyti, ar metodas yra perrašytas ar perkrautas.

Visa tai pirmiau.

Šiomis sąlygomis šios sąlygos apibūdina, kaip potipio santykis priklauso nuo tipo konversijų. Tai yra, jei A ir B yra tipai, f yra tipo konvertavimas ir ≤ yra potipio santykis (ty A ≤ B reiškia, kad A yra B potipis), turime

  • f yra kovariacija, jei iš A ≤ B tai reiškia, kad f(A) ≤ f(B)
  • f yra prieštaringas, jei iš A ≤ B matyti, kad f(B) ≤ f(A)
  • f yra nepastovus, jei nė vienas iš pirmiau minėtų atvejų nėra svarbus

Apsvarstykite pavyzdį. Leiskite f(A) = List<A> , kur List paskelbtas

 class List<T> { ... } 

Ar tai kovariantas, kontrastinis ar invariškas? Kovariantas reikštų, kad List<String> yra List<Object> subtipas, prieštaraujantis, kad List<Object> yra List<String> ir invariantinis potipis, kad nė vienas iš kitų potipių, t.y. List<String> ir List<Object> yra negrįžtami tipai. „Java“ pastarasis yra teisingas, sakome (šiek tiek neoficialiai), kad generiniai vaistai yra invariantai.

Kitas pavyzdys. Tegul f (A) = A[] . Ar tai kovariantas, kontrastinis ar invariškas? Tai reiškia, kad String [] yra String [] subtieto objektų [], Object [] potipis, ar tai nėra kito tipo potipis? (Atsakymas: „Java“, masyvai yra koviniai)

Tai buvo gana abstrakti. Norėdami, kad ji būtų tikslesnė, pažiūrėkime, kurios operacijos „Java“ yra apibrėžtos pagal potipį. Paprasčiausias pavyzdys yra priskyrimas. Patvirtinimas

 x = y; 

sukompiliuos tik jei tipo (y) le; (X) tipas. Tai yra, mes tiesiog sužinojome, kad pareiškimai

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

nebus kompiliuojama į java, bet

 Object[] objects = new String[1]; 

bus.

Kitas pavyzdys, kai potipio santykių klausimai yra metodo iškvietimo išraiška:

 result = method(a); 

Neoficialiai šis operatorius vertinamas priskiriant A vertę pirmajam metodo parametrams, tada vykdant metodo kūną ir paskui priskiriant metodų grąžinimo vertę. Kaip ir paprastas tikslas paskutiniame pavyzdyje, "dešinė pusė" turėtų būti "kairiosios" dalies potipis, t.y. Šis pareiškimas gali būti galiojantis tik tuo atveju, jei (a) le; typeof (parametras (metodas)) ir grąžinimo tipas (metodas) le; TipasOf (rezultatas). Tai yra, jei metodas yra paskelbtas:

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

nė viena iš šių išraiškų nesudarys:

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

bet

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

bus.

Kitas pavyzdys yra tai, kai klausimai yra subtipiniai. Apsvarstykite:

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

kur

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

Neoficialiai, vykdymo laikas jį perrašys:

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

Kad pasirinkta linija būtų sukompiliuota, svarbiausio metodo parametrų parametras turi būti viršutinio metodo parametro supertype, o grąžinimo tipas - viršutinio metodo vieno tipo potipis. Formaliai kalbant, f (A) = parametrertype (asdeklaredino (A) metodas) turi būti bent prieštaringas, o jei f (A) = grįžtamoji rūšis (asdeklaredino metodas (A)), turi būti bent jau kovariškas.

Atkreipkite dėmesį į „bent“ aukščiau. Tai yra minimalūs bet kokios pagrįstos statinio tipo saugaus objekto programavimo kalbos reikalavimai, tačiau programavimo kalba gali pasirinkti griežtesnę. „Java 1.4“ atveju parametrų tipai ir grąžinto metodo tipai turi būti identiški (išskyrus tipo ištrynimą), kai svarbiausi metodai, tai yra tipety parametras (asdeclaredin (A) metodas) = ​​tipo parametras (asdeclaredin (B) metodas), kai yra viršesnis. Pradedant nuo „Java 1.5“, pakartotinai apibrėžus, leidžiama naudoti kovariantinius grąžinimo tipus, t. Toliau bus sukompiliuota „Java 1.5“, bet ne „Java 1.4“:

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

Tikiuosi, kad apėmė viską - ar greičiau, subraižiau paviršių. Tačiau tikiuosi, kad tai padės suprasti abstrakčią, bet svarbią tipo dispersijos sąvoką.

185
13 дек. Atsakymą pateikė meriton 13 d 2011-12-13 01:51 '11 ne 1:51 2011-12-13 01:51

Atsižvelgiant į tokią sistemą kaip java ir klasės:

Bet kokio T tipo objektą galima pakeisti T tipo potipiu.

TIPO GALIMYBĖS - KLASĖS METODAI TURI ATSIŽVELGIANT Į TIKSLĄ

 class A { public S f(U u) { ... } } class B extends A { @Override public T f(V v) { ... } } B b = new B(); t = bf(v); A a = ...; // Might have type B s = af(u); // and then do V v = u; 

Galite matyti, kad:

  • T turi būti S (C kovariant) potipis , nes B yra A potipis .
  • V turi būti U supertpe (kontrastinė, kaip priešinga paveldėjimo kryptis).

Dabar tai prieštarauja faktui, kad B yra A. potipis. Tolesnės stipresnės rūšys gali būti įvestos su daugiau specifinių žinių. Be potipio.

Kovarijus (prieinamas „Java“) yra naudinga pasakyti, kad grąžinamas konkretesnis pogrupio rezultatas; ypač tada, kai A = T ir B = S. Kontravaracija sako, kad esate pasirengęs dirbti su bendresniu argumentu.

7
13 дек. Joop Eggen atsakymas gruodžio 13 d 2011-12-13 02:12 '11, 2:12 2011-12-13 02:12

Kiti klausimai apie žymą arba Užduoti klausimą