Na przykład:
Że mam zajęcia A
, B
, C
. Mam dwa interfejsy, nazwijmy je IAnimal
i IDog
. IDog
dziedziczy po IAnimal
. A
i B
są IDog
, chociaż C
nie jest, ale jest IAnimal
.
Ważną częścią jest to, że IDog
nie zapewnia żadnej dodatkowej funkcjonalności. Służy wyłącznie do zezwalania A
i przekazywania B
, ale nie C
do przekazania, jako argumentu dla niektórych metod.
Czy to zła praktyka?
object-oriented
interfaces
Kendall Frey
źródło
źródło
IAnimal
iIDog
są okropnymi nazwami tautologicznymi!MyProject.Data.IAnimal
iMyProject.Data.Animal
są lepsze niżMyProject.Data.Interfaces.Animal
iMyProject.Data.Implementations.Animal
Interface
alboImplementation
, czy w powtarzalnym prefiksie, czy też w przestrzeni nazw, jest to tautologia w obu kierunkach i narusza DRY.Dog
to wszystko, o co powinieneś dbać.PitBull extends Dog
nie potrzebuje też redundancji implementacji, słowoextends
mówi mi wszystko, co muszę wiedzieć, przeczytaj link, który zamieściłem w moim oryginalnym komentarzu.Odpowiedzi:
Interfejs, który nie ma żadnego członka lub ma dokładnie takie same elementy z innym interfejsem, który jest dziedziczony z tego samego interfejsu o nazwie Interfejs znaczników i używasz go jako znacznika.
Nie jest to zła praktyka, ale interfejs można zastąpić atrybutami (adnotacjami), jeśli używany język go obsługuje.
Mogę śmiało powiedzieć, że nie jest to zła praktyka, ponieważ widziałem intensywne użycie wzoru „Interfejs znacznika” w Orchard Project
Oto próbka z projektu Orchard.
Proszę zapoznać się z interfejsem znacznika .
źródło
C
metody do metody oczekującejIDog
.Kennel
klasę, która przechowuje listęIDog
s.Tak, to zła praktyka w prawie każdym języku.
Nie ma typów do kodowania danych; pomagają udowodnić, że Twoje dane idą tam, gdzie powinny, i zachowują się tak, jak powinny. Jedynym powodem podtypu jest zmiana zachowania polimorficznego (i nie zawsze wtedy).
Ponieważ nie ma potrzeby pisania, implikowane jest to, co może zrobić IDog. Jeden programista myśli jedną rzecz, inny myśli inną i wszystko się psuje. Lub rzeczy, które reprezentuje, zwiększają się, ponieważ potrzebujesz bardziej precyzyjnej kontroli.
[edytuj: wyjaśnienie]
Chodzi mi o to, że robisz jakąś logikę opartą na interfejsie. Dlaczego niektóre metody mogą działać tylko z psami, a inne z jakimkolwiek zwierzęciem? Ta różnica jest umową dorozumianą, ponieważ nie ma rzeczywistego członka, który zapewniłby różnicę; brak rzeczywistych danych w systemie. Jedyną różnicą jest interfejs (stąd komentarz „bez pisania na klawiaturze”), co oznacza, że różni się on między programistami. [/edytować]
Niektóre języki zapewniają mechanizmy cech, które nie są takie złe, ale te zwykle koncentrują się na możliwościach, a nie na wyrafinowaniu. Mam z nimi niewielkie doświadczenie, więc nie mogę porozmawiać z najlepszymi praktykami. W C ++ / Java / C # jednak ... nie dobrze.
źródło
Kennel
klasę, która przechowuje listęIDog
s.Znam tylko język C #, więc nie mogę tego powiedzieć ogólnie o programowaniu OO, ale jako przykład w języku C #, jeśli chcesz sklasyfikować klasy, oczywistymi opcjami są interfejsy, właściwość enum lub niestandardowe atrybuty. Zwykle wybieram interfejs bez względu na to, co myślą inni.
źródło
Nie ma nic złego w posiadaniu interfejsu, który dziedziczy inny interfejs bez dodawania nowych członków, jeśli można oczekiwać, że wszystkie implementacje tego drugiego interfejsu będą w stanie użytecznie robić rzeczy, których niektóre implementacje pierwszego nie mogą. Rzeczywiście, jest to dobry wzorzec, który IMHO powinien był być bardziej używany w takich rzeczach, jak .NET Framework, zwłaszcza że implementator, którego klasa naturalnie spełniałaby ograniczenia wynikające z bardziej pochodnego interfejsu, może to wskazać po prostu przez implementację bardziej pochodnego interfejsu , bez konieczności zmiany kodu implementacyjnego członka ani deklaracji.
Załóżmy na przykład, że mam interfejsy:
IImmutableFoo.AsImmutable()
Oczekuje się, że wdrożenie się zwróci;IMaybeMutableFoo.AsImmutable()
oczekuje się, że implementacja klasy mutable zwróci nowy głęboko niezmienny obiekt zawierający migawkę danych. Procedura, która chce przechowywać migawkę danych przechowywanych w,IMaybeMutableFoo
może oferować przeciążenia:W przypadkach, w których kompilator nie wie, że rzeczą do zapisania jest
IImmutableFoo
, wywołaAsImmutable()
. Funkcja powinna szybko wrócić, jeśli element jest już niezmienny, ale wywołanie funkcji przez interfejs nadal zajmuje trochę czasu. Jeśli kompilator wie, że element jest jużIImmutableFoo
, może pominąć niepotrzebne wywołanie funkcji.źródło