2016-02-16 21 views
6

Próbuję napisać jakiś ogólny kod, ale nie mogę się pozbyć błędu Type of 'PROPERTY' is not a subtype of the overridden property.Kotlin: nadpisanie ogólnej właściwości podtypu

Uproszczona wersja mojego kodu:

abstract class BaseP<V> { 
    var view: V? = null 
} 

abstract class BaseF { 
    fun smth() { 
     pp.view = this 
    } 
    abstract val pp: BaseP<BaseF> 
} 

abstract class SubF: BaseF() { 
    abstract override val pp: BaseP<SubF> 
    // Error:(20, 30) Type of 'pp' is not a subtype of the overridden property 'public abstract val pp: BaseP<BaseF> defined in BaseF' 
} 

Okazało się, że błąd może być @Suppress -ed, ale wątpię, że jest najlepszy i jedyny sposób. Czy jest coś lepszego?

I ostatecznie nie mogę zrozumieć, dlaczego subtypeA<subtypeB> nie jest podtypem baseA<baseB>, czy ktoś może to wyjaśnić?

+0

co linia wyrzuca błąd? – voddan

Odpowiedz

7

Po pierwsze, SubtypeA<B> jest podtypem BaseA<B>, więc problem polega na podtypach parametrów generycznych.

Odpowiedź dotyczy Kotlin generics variance, która jest podobna do that of Java.

Dlaczego SubtypeA<SubtypeB> nie liczy się jako podtyp BaseA<BaseB>?

generyczni niezmienna domyślnie, co oznacza, że ​​nawet w prostszym przypadku, dla klasy A<T>, A<SubtypeB> i A<BaseB> nie podtypy siebie, o ile nie jest to inaczej określone przez modyfikatory wariancji in i out (lub Java wildcards) .

dwa przypadki są możliwe:

  • Jeśli chcesz tylko do wziąćT instancji z instancjami klasy A, a następnie można użyć out modyfikator: A<out T>.

    Tutaj A<SubtypeB> staje się podtypem A<BaseB>, ponieważ od A<SubtypeB> można oczywiście wziąć instancje BaseB, a nie odwrotnie.

  • Jeśli chcesz tylko do przejściuT do metod klasie, a następnie użyć in modyfikatora w deklaracji klasy: A<in T>.

    I tu A<BaseB> jest podtypem A<SubtypeB>, ponieważ każdy przypadek A<BaseB> można również otrzymać SubtypeB do metod, ale nie odwrotnie.

Jeśli obaj przechodzą i wziąć T do/z klasy A<T>, to jedynym rozwiązaniem dla T ma być niezmienna, tak że ani A<SubB> ani A<SuperB> są podtypy A<B>: w przeciwnym razie prowadziłoby do sprzeczności Do powyższego.

I to jest właśnie przypadek: W BaseP<B>, jesteś zarówno biorąc pozycji V i oddanie tych w view nieruchomości, tak V może być tylko niezmienna i BaseP<SubF> nie jest podtypem BaseP<BaseF>, nie jest SubP<SubF>.

Powiązane problemy