2010-06-15 12 views
13

Ja w zasadzie chcąc to zrobić:Jak dziedziczyć po parametrze generycznym?

class UILockable<T> : T 
    where T : UIWidget 
{ 
} 

Jednak to nie działa. Widziałem ludzi, zaleca się to zrobić:

class UILockable<T> 
    where T : UIWidget 
{ 
    private T _base; 
} 

Wymagałoby to mnie zastąpić każdy UILockable funkcja musiałaby i przekazuje go do T. Jest to niemożliwe, ponieważ T może pochodzić od UIWidget i mają unikalne abstrakcyjne/wirtualnego własne metody.

Czy nie można po prostu odziedziczyć po T?

+0

Zastanów się, czy wymusić typ ogólny, aby zaimplementować określony interfejs. Nie wiesz, jaki jest dokładny typ T, a jeśli szukasz konkretnych metod, które T ma lub może nie mieć, to nie zadziała. Spraw, aby wszystkie takie obiekty wprowadzały ILockable, które wymusza takie metody, jak kontrakt. – drharris

+1

Jeśli nie ma potrzeby zastępowania metod chronionych w celu uzyskania logiki blokowania, można przeprojektować to za pomocą obiektu usługi blokowania, który łączy instancje UIWidget z obiektami LockContext używanymi w logice blokowania. Nie sądzę, że dziedziczenie to dobre pojęciowe dopasowanie do tego, co próbujesz zrobić, ponieważ starasz się ogólnie zwiększyć funkcjonalność, a nie wyrażać konkretnej relacji "jest-a". –

+0

możliwy duplikat [Dziedziczenia z ograniczonym typowym parametrem typu] (http://stackoverflow.com/questions/1420581/inheritance-on-a-constrained-generic-type-parameter) – joce

Odpowiedz

16

Nie można dziedziczyć po parametrze rodzajowym. Generics C# bardzo różnią się od szablonów C++. Dziedziczenie z parametru type wymaga, aby klasa miała zupełnie inną reprezentację na podstawie parametru type, co nie dzieje się z typami .NET. Są identyczne na poziomie IL i natywnym (dla wszystkich argumentów typu referencyjnego).

3

Nie, nie ma. Jednak ja naprawdę nie rozumiem argumentu przeciwko konieczności UILockable<T> dziedziczą z UIWidget i przekazuje wszystkie połączenia na Twój T:

class UILockable<T> : UIWidget 
    where T : UIWidget 
{ 
    private readonly T t; 

    public void SomeMethod() 
    { 
     this.t.SomeMethod(); 
    } 
} 

Nie dbam o specyfice realizacji T „s of UIWidget - tylko, że jest implementacja UIWidget.

+3

Myślę, że on mówi, że jeśli ty zrób to w ten sposób, wszelkie metody 'T' które nie są określone przez' UIWidget' nie będą dostępne. –

+1

W takim przypadku konieczne byłoby dodanie bardziej ogólnych ograniczeń, takich, że T rozszerza UIWidget i implementuje również niektóre interfejsy. –

3

Pomyśl o tym w ten sposób: Kiedy Rodzaj B dziedziczy od typu , jesteś uznającą B jest podobny do (gdzie podobieństwo oznacza, że ​​można użyć B wszędzie, gdzie będziesz używać A). Teraz, ponieważ takie podobieństwo nie jest symetryczny masz że B jest podobna do ale nie jest podobna do B. Ponadto B i C może zarówno być podobny do (to znaczy oba pochodzą od ) nie są podobne do siebie.

Więc co chcesz zadeklarować, że odblokowania jest podobny do wszystkiego, co jest podobne do UIWidget, ale to niemożliwe, ponieważ typ podobieństwo nie jest przechodnia (czyli jeśli B jest podobna do i C jest podobna do A nie można powiedzieć, że B jest podobna do C).

+0

@Robert Dlaczego ten nie jest odpowiedzią? – AgentFire

+1

@AgentFire: Ponieważ pomija najważniejszy punkt - 'Unlockable ' byłby podobny do 'T', a nie do innych podklas' UIWidget' i byłby podobny z powodu dziedziczenia zachowania z 'T'. –

0

Nie można dziedziczyć z argumentu Typowy. C# to ściśle napisany język. Wszystkie typy i hierarchia dziedziczenia muszą być znane podczas kompilacji. Generics .Net znacznie różnią się od szablonów C++.

A kiedy jesteś tak pewny, że typem T będzie typ UIWidget, to dlaczego nie dziedziczysz z samego interfejsu UIWidget. Czy kiedykolwiek będzie to dozwolone [zakładając, zakładając, wiem, że to nigdy nie będzie możliwe] co byś osiągnął dziedzicząc swoją klasę od T, która jest już typu UIWidget. W czasie projektowania będziesz kodować tylko na UIWidget, więc dlaczego nie dziedziczyć bezpośrednio z interfejsu UIWidget.

+0

Dlaczego nie dziedziczyć bezpośrednio z 'UIWidget'? * Mixins *. Tylko dlatego, że mixin może używać tylko podstawowego interfejsu dostarczanego przez 'UIWidget', nie oznacza to, że konsument nie chciałby mieć zachowania mixin i bardziej wyspecjalizowanego zachowania widgetów * na tym samym obiekcie *. –

+0

Będąc silnie statycznie wpisanym i zabraniającym tego dziedziczenia są całkowicie ortogonalne. – Puppy

Powiązane problemy