Klasa kowariantna

Klasa kowariantna
  • Rejestracja: dni
  • Ostatnio: dni
0

Cześć, nie bardzo mogę zrozumieć czemu w Scali klasy kowariantne mogą mieć tylko gettery, a kontrawariantne settery? Na razie na tapetę wziąłem sobie klasy kowariantne.
Przy takiej deklaracji klasy:

Kopiuj
class CovariantClass[+T] (var x: T) {
}

//bład
covariant type T occurs in contravariant position in type T of value x_=
class CovariantClass[+T] (var x: T) {

Otrzymam błąd gdyż przez var utworzy się getter i setter. Przeczytałem, że w takiej klasie może być setter jednak musi on zwracać nową instancję - tu jednak pojawia się problem, że nie umiem napisać takiego settera :(
Mój setter wygląda tak:

Kopiuj
def setx_= (value: T): CovariantClass[T] = new CovariantClass[T](value)

Jednak IDE podpowiada mi taki sam błąd jak we wcześniejszym przypadku.
Podsumowując, czemu klasy kowariantne mogą mieć tylko getter?
Jak napisać taki setter?

lion137
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5023
0

Skąd ten błąd?

Kopiuj
//bład
covariant type T occurs in contravariant position in type T of value x_=
class CovariantClass[+T] (var x: T) {

Ta: https://stackoverflow.com/questions/9619121/why-is-parameter-in-contravariant-position#9619950 odpowiedź tłumaczy. Jeszcze, cytując twórcę Scali:

  • parametry covariantne mogą pojawiać sie tylko jako zwracane z funkcji;
  • parametry contravariantne mogą się pojawiać tylko jako parametry;
  • invariantne mogą pojawiać się wszędzie.
Wibowit
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: XML Hills
1

Zamiast:

Kopiuj
def setx_= (value: T): CovariantClass[T] = new CovariantClass[T](value)

Daj coś w rodzaju (pisane na szybko, mogą być błędy):

Kopiuj
def setx_=[U >: T](value: U): CovariantClass[U] = new CovariantClass[U](value)

Więcej info: http://docs.scala-lang.org/tutorials/tour/lower-type-bounds.html.html

Podsumowując, czemu klasy kowariantne mogą mieć tylko getter?

Mutowalność + kowariancja = problem. Przykład w Javie, gdzie tablice są mutowalne i kowariantne:

Kopiuj
Integer[] integery = new Integer[] { 1 };
Object[] obiekty = integery; // kowariantne przypisanie; referencje wskazują na tę samą tablicę
obiekty[0] = "ala ma kota"; // tutaj mamy settera (ten zapis jest efektywnie setterem na tablicy), który powoduje wybuch

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.