2012-11-22 15 views
13

Próbuję utworzyć system dziedziczenia interfejsu, który używa tej samej właściwości, ale zawsze innego typu pochodnego. Tak więc podstawowa właściwość powinna zostać w jakiś sposób przesłonięta lub ukryta przez interfejs wyprowadzający.Czy pochodne właściwości interfejsu C# zastępują właściwości interfejsu bazowego o tej samej nazwie?

Weźmy na przykład dwa interfejsy, Mężczyzna i Kobieta, które wywodzą się od Męża i żony, a także interfejsy. Interfejsy "Człowiek i mąż" mają właściwość "kochanie", podczas gdy kobieta i żona mają "kochaną" własność. Teraz właściwość "kochanie" mężczyzny jest typem "Kobieta", podczas gdy właściwość "kochanie" Męża powinna być Żoną (pochodzącą od Kobiety). I to samo z "ulubioną" kobietą i żoną.

public interface Man // base interface for Husband 
{ 
    Woman sweetheart { get; set; } 
} 

public interface Woman // base interface for Wife 
{ 
    Man darling { get; set; } 
} 

public interface Husband : Man // extending Man interface 
{ 
    new Wife sweetheart { get; set; } // narrowing "sweetheart" property's type 
} 

public interface Wife : Woman // extending Woman interface 
{ 
    new Husband darling { get; set; } // narrowing "darling" property's type 
} 

public class RandomHusband : Husband // implementing the Husband interface 
{ 
    private RandomWife wife; 
    public Wife sweetheart { get { return wife; } set { wife = value; } } 
} 

public class RandomWife : Wife // implementing the Wife interface 
{ 
    private RandomHusband husband; 
    public Husband darling { get { return husband; } set { husband = value; } } 
} 

Ten kod jest niepoprawny, nie działa. Otrzymuję powiadomienie, że nie zaimplementowałem podstawowych właściwości Man.sweetheart i Woman.darling i że zaimplementowane Husband.sweetheart i Wife.darling nie będą działać, ponieważ typy nie są zgodne. Czy istnieje sposób zawężenia typu właściwości do typu pochodnego? Jak osiągnąć to w C#?

+0

ciekawe pytanie :) – nawfal

Odpowiedz

2

będzie trzeba jeszcze satisy interfejsy mężczyzna i kobieta, jak i mąż i żona ...

public class RandomWife : Wife // implementing the Wife interface 

    { 
     private RandomHusband husband; 
     public Husband darling { get { return husband; } set { husband = value; } } 
     public Man Wife.darling { get { return husband; } set { /* can't set anything */ } } 

    } 
+0

Nie możesz ustawić męża w swojej jawnej implementacji bez obsady i nie ma gwarancji, że będzie to instancja RandomHusband. Jeśli zestaw; można usunąć z IWife/IHusband, byłoby to idealne. – drch

+0

bardzo dobry punkt ... –

+0

W końcu zrobiłem to po swojemu i wszystko jest w porządku. Dzięki za pomysł, Keith. Właściwie to odpowiedź Lee była najbliższa temu, o co go poprosiłem, tak jak o to pytałem, ale w prawdziwym kodzie miałem bardziej złożoną sytuację niż przedstawiłem. I okazało się, że prostota twojej metody była właśnie taka. –

13

Można to zrobić przez parametryzacja swoje Man i Woman interfejsy z konkretnymi typami realizacji:

public interface IMan<M, W> 
    where M : IMan<M, W> 
    where W : IWoman<W, M> 
{ 
    W Sweetheart { get; set; } 
} 

public interface IWoman<W, M> 
    where W : IWoman<W, M> 
    where M : IMan<M, W> 
{ 
    M Darling { get; set; } 
} 

Twoje implementacje są następnie:

public class Man : IMan<Man, Woman> 
{ 
    public Woman Sweetheart { get; set; } 
} 

public class Woman : IWoman<Woman, Man> 
{ 
    public Man Darling { get; set; } 
} 

public class Husband : IMan<Husband, Wife> 
{ 
    public Wife Sweetheart { get; set; } 
} 

public class Wife : IWoman<Wife, Husband> 
{ 
    public Husband Darling { get; set; } 
} 

Ponieważ typy się dość skomplikowane, warto rozważyć przeniesienie relacji do zewnętrznego klasy/interfejsu:

public interface Relationship<TMan, TWoman> 
    where TMan : Man 
    where TWoman : Woman 
{ 
    TMan Darling { get; } 
    TWoman Sweetheart { get; } 
} 

public class Marriage : Relationship<Husband, Wife> 
{ 
} 

Następnie można użyć tej klasy, aby zachować bezpieczeństwo typ gdy ma do czynienia z konkretnymi wdrożeniami:

public static void HandleMarriage(Relationship<Husband, Wife> marriage) 
{ 
    Husband h = marriage.Darling; 
    Wife w = marriage.Sweetheart; 
} 
Powiązane problemy