2010-03-03 10 views
5

Wdrażam zestaw klas i odpowiednich interfejsów, w których chcę, aby każda klasa miała zestaw wspólnych właściwości i zestaw wyspecjalizowanych właściwości, które są specyficzne tylko dla tej klasy. Więc Zastanawiam zdefiniowanie interfejsów wzdłuż linii:Dziedziczenie wielu interfejsów

interface ICommon {...} // Members common to all widgets 
interface IWidget1 {...} // specialized members of widget type 1 
interface IWidget2 {...} // specialized members of widget type 2 

Staram się wybierać pomiędzy posiadaniem dziedziczenia w interfejsach, lub w klasie. Tak, szczególnie, że można albo zrobić to tak:

interface IWidget1 : ICommon {...} 
interface IWidget2 : ICommon {...} 
class Widget1 : IWidget1 {...} 
class Widget2 : IWidget2 {...} 

... albo tak ...

class Widget1: ICommon, IWidget1 {...} 
class Widget2: ICommon, IWidget2 {...} 

Czy jest jakiś powód, aby przejść jedną lub drugą stronę?

Aktualizacja: czy wpłynęłoby na odpowiedź, gdyby klasy musiały być widoczne w COM?

Odpowiedz

6

Powinieneś wybrać dziedziczenie interfejsu wtedy i tylko wtedy, gdy typ implementujący IWidget1 musi również wdrożyć ICommon. W obu przypadkach klasa będzie implementować zarówno IWidget1, jak i ICommon oddzielnie. Jedyna różnica polega na tym, że jeśli uczynisz IWidget1 "pochodną" od ICommon, wymusisz fakt, że IWidget1 musi również być ICommon.

Dobrym przykładem jest IEnumerable i ICollection. Każdy ICollection ma gwarantowaną liczbę IEnumerable, więc ICollection pochodzi z IEnumerable. Gdyby było to zgodne z prawem lub miało sens, aby być zbiorem, ale nie było możliwe do wyliczenia, wówczas implementatorzy ICollection nie musieliby implementować IEnumerable.

Którąkolwiek opcję wybierzesz, nie wpłynie to na widoczność modelu COM. .NET nadal będzie eksportować interfejsy osobno, jeśli poprawnie przywołam.

+0

Dobrze, tak. Wszystkie typy Widget MUSZĄ zaimplementować ICommon. To jest powód, aby wymusić jego wdrożenie w każdym widżecie. –

+1

W takim razie zdecydowanie powinieneś mieć IWidget1 od ICommon. – Josh

3

Stosuj zasadę podstawiania Liskov, aby pomóc sobie w udzieleniu odpowiedzi.

Jeśli IWidget1 można zastąpić wszystkimi klientami pracującymi w kategoriach ICommon1, to możesz dziedziczyć IWidget1 z ICommon1. Jeśli nie, przejdź do klasy implementującej wiele interfejsów.

+0

Czy to nie daje tego samego wyniku? –

+0

@Tim - czy możesz rozwinąć? Chodziło mi o to, że jeśli można podstawić obiekt IWidget1 dla całego kodu oczekującego ICommon1 i ma sens posiadanie elementu IWidget1 w domenie, to można przejść z podejściem dziedziczenia interfejsu. Jeśli nie, niech ta sama klasa implementuje wiele interfejsów. – Gishu

+0

OK Rozumiem, co masz na myśli. Dzięki. –

0

Dziedziczenie zależy od atrybutu/zachowania klasy lub interfejsu. Jeśli zachowania w ustawieniach IWidget1 i IWidget2 obejmują wszystkie zachowania w ICommon, z pewnością możesz dziedziczyć podobnie jak IWidget1 : ICommon i IWidget2 : ICommon i nie ma problemu dotyczącego ComVisible. To jest po prostu koncepcja OOPS.

1

Jest jeszcze jedna uwaga, która moim zdaniem nie została uwzględniona w innych odpowiedziach.

Jeśli czerpać IWidgetX z ICommon, a następnie wymyślić widget, który ma zachowanie zarówno IWidget1 i IWidget2 można zrobić wiele implementacji interfejsu:

class Widget3 : IWidget1, IWidget2 

Jeśli oba były interfejs pochodzą z ICommon, wtedy będziesz mieć dwie implementacje ICommon w swojej klasie. To nie jest duży problem i może być obsłużony przez multiple interface implementation, ale zmienia logikę.

Z drugiej strony, jeśli nie czerpią IWidgetX z ICommon, można po prostu wdrożyć wszystkie trzy, a nie mają do czynienia z wyraźną realizacji:

class Widget3 : IWidget1, IWidget2, ICommon 

Tak więc, jeśli jest to możliwe, że może być konieczne taka klasa Widget3 - lepiej nie wyprowadzać interfejsów IWidgetX z ICommon

+0

+1 dzięki za przydatną nową perspektywę. –

+0

Dzięki Tim - choć okazuje się, że nie mam racji! Wkopałem się nieco głębiej w tę implementację wielu interfejsów i faktycznie nie masz dwóch implementacji ICommon - gdybyś miał, to obsada (ICommon) (nowy Widget3()) byłaby nierozwiązywalna. Opisałem sytuację bardziej szczegółowo [w tym wpisie na blogu] (http://stefankiryazov.blogspot.com/2011/09/luke-whos-your-father-multiple.html) Argument przeciw wyprowadzeniu IWidgetX od ICommon jest nadal częściowo ważny – Vroomfundel

Powiązane problemy