2009-02-04 8 views
47

Powiedz, że mam interfejs IFoo i chcę, aby wszystkie podklasy IFoo zastąpiły metodę obiektu ToString. czy to możliwe?Wymuś podklasy interfejsu implementującego ToString

prostu dodając metoda sygnatury IFoo jako taki nie działa:

interface IFoo 
{ 
    String ToString(); 
} 

ponieważ wszystkie podklasy przedłużyć Object i zapewnić implementację tamtędy, więc kompilator nie narzekać. Jakieś sugestie?

+0

http: // stackoverflow.com/questions/239408/can-i-force-subclasses-to-override-a-method-without-making-it-abstract <-? podobnie? lub po prostu bardzo podobne? –

Odpowiedz

68

Nie wierzę, że można to zrobić za pomocą interfejsu. Można użyć abstrakcyjną klasę bazową choć:

public abstract class Base 
{ 
    public abstract override string ToString(); 
} 
+0

Miałem nadzieję, że będę trzymać się interfejsów, skoro już je napisałem, zgaduję, że będę musiał ugryźć bullet i przełączyć klasy abstrakcyjne. Dzięki. – rjohnston

+0

Świetna odpowiedź (i myślę, że jedyna rozsądna możliwość), ale ma wadę w brak wsparcia C# dla wielu dziedziczenia. Każda klasa, która musi dziedziczyć po Base nie może dziedziczyć z żadnej innej klasy innej niż klasa podstawowa, tj. Klasa MyClass: ThirdPartyClass, Base // mot possible – AlanK

21
abstract class Foo 
{ 
    public override abstract string ToString(); 
} 

class Bar : Foo 
{ 
    // need to override ToString() 
} 
+1

Pytanie brzmiało "czy mogę to zrobić za pomocą interfejsu?", A nie "jak to zrobić?" , ale i tak dzięki. – rjohnston

0

Nie sądzę, można wymusić żadnych sub-klasę ręcznym dowolnej metody wirtualne podstawy swojej klasie, chyba że te metody są abstrakcyjne.

1

Implementacja metody interfejsu niejawnie zamyka metodę (i ją przesuwa). Tak więc, chyba że powiesz inaczej, pierwsza implementacja interfejsu kończy łańcuch nadpisywania w języku C#.

Essential .NET

Streszczenie class = Twój znajomy

Sprawdź this question

6

Jon & Andrew: To streszczenie sztuczka jest naprawdę przydatna; Nie miałem pojęcia, że ​​możesz zakończyć łańcuch, uznając go za abstrakcyjny. Pozdrawiam :)

W przeszłości, kiedy mam wymagało toString() być nadpisane w klasach pochodnych, zawsze stosowany wzór jak następuje:

public abstract class BaseClass 
{ 
    public abstract string ToStringImpl(); 

    public override string ToString() 
    { 
     return ToStringImpl(); 
    }  
} 
1

Znam ten nie odpowie Twoje pytanie, ale ponieważ nie ma sposobu, aby zrobić to, o co prosisz, pomyślałem, że podzielę się własnym podejściem, aby inni mogli je zobaczyć.

Używam hybrydy proponowanych przez Marka i Andrew rozwiązań.

W mojej aplikacji, wszystkie domeny jednostki wywodzą się z abstrakcyjnego bazowej klasy:

public abstract class Entity 
{ 
    /// <summary> 
    /// Returns a <see cref="System.String"/> that represents this instance. 
    /// </summary> 
    public override string ToString() 
    { 
     return this is IHasDescription 
        ? ((IHasDescription) this).EntityDescription 
        : base.ToString(); 
    } 
} 

Interfejs sama tylko definiuje prostą akcesor:

public interface IHasDescription : IEntity 
{ 
    /// <summary> 
    /// Creates a description (in english) of the Entity. 
    /// </summary> 
    string EntityDescription { get; } 
} 

Więc teraz jest spadek-back wbudowany mechanizm - lub inaczej: Entity, który implementuje IHasDescription, musi dostarczyć EntityDescription, ale dowolny Entity może nadal konwertować na ciąg znaków.

Wiem, że nie różni się to radykalnie od innych proponowanych tutaj rozwiązań, ale podoba mi się pomysł zminimalizowania odpowiedzialności typu bazowego Entity, więc implementacja interfejsu opisu pozostaje opcjonalna, ale jesteś zmuszony faktycznie zaimplementuj metodę opisu, jeśli implementujesz interfejs.

IMHO, interfejsy, które są realizowane przez bazowej klasy object nie powinno „Count”, jak realizowane - byłoby miło mieć opcję kompilatora, ale, no cóż ...

+0

Możesz użyć 'as' zamiast' is', aby uniknąć drugiego rzutu. – chwarr