Kiedy używać interfejsu zamiast klasy abstrakcyjnej i odwrotnie?

To może być ogólne Pytanie OOP. Chciałem zrobić ogólne porównanie między interfejsem i klasą abstrakcyjną na podstawie ich użycia.

Kiedy chcesz użyć interfejsu, a kiedy chcesz użyć klasy abstrakcyjnej?

Author: Ravindra babu, 2009-01-26

21 answers

Napisałem o tym Artykuł:

Klasy abstrakcyjne i interfejsy

Podsumowanie:

Kiedy mówimy o klasach abstrakcyjnych definiujemy cechy typu obiektowego; określamy czym jest obiekt.

Kiedy mówimy o interfejsie i definiujemy możliwości, które obiecujemy zapewnić, mówimy o zawarciu umowy o co obiekt może zrobić.

 360
Author: Jorge Córdoba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-21 19:34:30

Klasa abstrakcyjna może mieć wspólny stan lub funkcjonalność. Interfejs jest tylko obietnicą zapewnienia stanu lub funkcjonalności. Dobra klasa abstrakcyjna zmniejszy ilość kodu, który musi zostać przepisany, ponieważ jego funkcjonalność lub stan mogą być współdzielone. Interfejs nie ma zdefiniowanych informacji do współdzielenia

 386
Author: Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-26 08:52:47

Osobiście prawie nigdy nie mam potrzeby pisania abstrakcyjnych klas.

Najczęściej widzę, że klasy abstrakcyjne są (mis) używane, to dlatego, że autor klasy abstrakcyjnej używa wzorca "metody szablonowej".

Problem z "metodą szablonową" polega na tym, że prawie zawsze jest ona w pewnym stopniu wprowadzana-Klasa "pochodna" wie nie tylko o "abstrakcyjnej" metodzie swojej klasy bazowej, którą implementuje, ale także o publicznych metodach klasy bazowej, mimo że większość razy nie trzeba do nich dzwonić.

(zbyt uproszczony) przykład:

abstract class QuickSorter
{
    public void Sort(object[] items)
    {
        // implementation code that somewhere along the way calls:
        bool less = compare(x,y);
        // ... more implementation code
    }
    abstract bool compare(object lhs, object rhs);
}

Więc tutaj, autor tej klasy napisał generyczny algorytm i zamierza używać go przez "specjalizowanie" go poprzez dostarczanie własnych "hooków" - w tym przypadku metody" porównywania".

Więc zamierzone użycie jest coś takiego:

class NameSorter : QuickSorter
{
    public bool compare(object lhs, object rhs)
    {
        // etc.
    }
}

Problem polega na tym, że niepotrzebnie połączyłeś ze sobą dwa pojęcia:

  1. sposób porównywania dwóch elementów (jaki element powinien idź pierwszy)
  2. metoda sortowania elementów (np. quicksort vs merge sort itd.)

W powyższym kodzie teoretycznie autor metody " compare "Może ponownie wywołać z powrotem do superklasowej metody" Sort"... nawet jeśli w praktyce nigdy nie będą tego chcieli i nie będą tego musieli robić.

Cena, jaką płacisz za to niepotrzebne sprzężenie, jest taka, że trudno jest zmienić superklasę, a w większości języków OO nie można jej zmienić w czasie wykonywania.

The alternatywną metodą jest użycie wzorca projektowego" strategii " zamiast:

interface IComparator
{
    bool compare(object lhs, object rhs);
}

class QuickSorter
{
    private readonly IComparator comparator;
    public QuickSorter(IComparator comparator)
    {
        this.comparator = comparator;
    }

    public void Sort(object[] items)
    {
        // usual code but call comparator.Compare();
    }
}

class NameComparator : IComparator
{
    bool compare(object lhs, object rhs)
    {
        // same code as before;
    }
}

Zauważ teraz: wszystko, co mamy, to interfejsy i konkretne implementacje tych interfejsów. W praktyce nie potrzebujesz niczego innego, aby wykonać projekt oo na wysokim poziomie.

Aby " ukryć "fakt, że zaimplementowaliśmy" sortowanie nazw "za pomocą klasy" QuickSort " i "NameComparator" , nadal możemy gdzieś napisać metodę fabryczną:

ISorter CreateNameSorter()
{
    return new QuickSorter(new NameComparator());
}

Any time you have a abstract class dasz radę... nawet jeśli istnieje naturalna relacja między klasą bazową a pochodną, Zwykle opłaca się je wyraźnie przedstawić.

Ostatnia myśl: wszystko, co zrobiliśmy powyżej, to" skomponowanie "funkcji" NameSorting "za pomocą funkcji" QuickSort "i funkcji" NameComparison"... w funkcyjnym języku programowania ten styl programowania staje się jeszcze bardziej naturalny, z mniejszą ilością kodu.

 75
Author: Paul Hollingsworth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-17 23:42:56

OK, po prostu "upokarzając" to sobie - tutaj jest to w kategoriach laika (Proszę mnie poprawić, jeśli się mylę) - wiem, że ten temat jest ooooooo, ale ktoś inny może się na niego kiedyś natknąć...

Klasy abstrakcyjne pozwalają na tworzenie schematów i pozwalają dodatkowo konstruować (implementować) właściwości i metody, które mają posiadać wszystkie ich potomkinie.

Interfejs z drugiej strony pozwala tylko zadeklarować, że chcesz właściwości i / lub metody z podana nazwa istnieje we wszystkich klasach, które ją implementują - ale nie określa, jak należy ją zaimplementować. Ponadto klasa może zaimplementować wiele interfejsów, ale może rozszerzyć tylko jedną klasę abstrakcyjną. Interfejs jest bardziej narzędziem architektonicznym wysokiego poziomu ( które staje się jaśniejsze, jeśli zaczniesz rozumieć wzorce projektowe) - Abstrakt ma stopę w obu obozach i może wykonać trochę brudnej roboty.

Po co używać jednego nad drugim? Pierwszy pozwala na bardziej konkretną definicję Potomków-ten ostatni pozwala na większy polimorfizm . Ten ostatni punkt jest ważny dla użytkownika końcowego/kodera, który może wykorzystać te informacje do implementacji A. P.I(nterface) w różnych kombinacjach/kształtach, aby dostosować je do swoich potrzeb.

Myślę, że był to dla mnie moment "żarówki" - pomyśl o interfejsach mniej od perpective autora, a bardziej od każdego kodera, który przychodzi później w łańcuchu, który dodaje implementację do projektu, lub rozszerzenie API.

 38
Author: sunwukung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-07 12:10:57

Moje dwa grosze:

Interfejs zasadniczo definiuje kontrakt, do którego każda klasa implementująca musi się stosować(implementować elementy interfejsu). Nie zawiera żadnego kodu.

Z drugiej strony, klasa abstrakcyjna może zawierać kod i mogą istnieć pewne metody oznaczone jako abstrakcyjne, które Klasa dziedzicząca musi zaimplementować.

Rzadkie sytuacje, kiedy używałem klas abstrakcyjnych, to kiedy mam domyślną funkcjonalność, że dziedzicząca klasa może nie być interesująca w nadpisywaniu, np. abstrakcyjnej klasy bazowej, od której dziedziczą niektóre wyspecjalizowane klasy.

Przykład (bardzo prymitywny!): Rozważ klasę bazową zwaną klientem, która ma abstrakcyjne metody, takie jak CalculatePayment(), CalculateRewardPoints() i niektóre nieabstraktowe metody, takie jak GetName(), SavePaymentDetails().

Wyspecjalizowane klasy, takie jak RegularCustomer i GoldCustomer odziedziczą po klasie bazowej Customer i zaimplementują własną logikę metod CalculatePayment() i CalculateRewardPoints(), ale ponownie użyją metod GetName() i SavePaymentDetails().

Możesz dodać więcej funkcjonalność do klasy abstrakcyjnej (czyli metody nieabstraktowe) bez wpływu na klasy potomne, które używały starszej wersji. Podczas gdy dodawanie metod do interfejsu wpłynie na wszystkie klasy implementujące go, ponieważ teraz będą one musiały zaimplementować nowo dodane elementy interfejsu.

Klasa abstrakcyjna ze wszystkimi elementami abstrakcyjnymi byłaby podobna do interfejsu.

 33
Author: PreethaA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-24 17:14:57

Kiedy zrobić to, co jest bardzo proste, jeśli masz jasne pojęcie w umyśle.

Klasy abstrakcyjne mogą być wyprowadzane, podczas gdy interfejsy mogą być implementowane. Jest jakaś różnica między nimi. Gdy wyprowadzamy klasę abstrakcyjną, relacja między klasą pochodną a klasą bazową jest relacją' jest'. na przykład pies jest zwierzęciem, Owca jest zwierzęciem, co oznacza, że klasa pochodna dziedziczy pewne właściwości z klasy bazowej.

Implementacja interfejsów, relacja jest "może być". np. pies może być psem szpiegowskim. Pies może być psem cyrkowym. Pies może być psem rasowym. Co oznacza, że wdrażasz pewne metody, aby coś zdobyć.

Mam nadzieję, że wyraziłem się jasno.

 28
Author: Aamir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-26 10:41:12

Jeśli patrzysz na Javę jako język OOP,

"interfejs nie zapewnia implementacji metod" Nie jest już ważne przy uruchomieniu Java 8. Teraz java dostarcza implementację w interfejsie dla metod domyślnych.

W prostych słowach, chciałbym użyć

interfejs: realizacji umowy przez wiele niepowiązanych ze sobą obiektów. Zapewnia" mA " możliwość.

klasa abstrakcyjna: Zaimplementować to samo lub różne zachowanie między wieloma powiązanymi obiektami. Tworzy ona relację" jest relacją".

Oracle website dostarcza kluczowych różnic między klasą interface i abstract.

rozważmy użycie klas abstrakcyjnych, jeśli:

  1. chcesz podzielić się kodem pomiędzy kilka ściśle powiązanych klas.
  2. spodziewasz się, że klasy rozszerzające Twoją klasę abstrakcyjną mają wiele popularnych metod lub pól lub wymagają modyfikatorów dostępu inne niż publiczne(takie jak chronione i prywatne).
  3. chcesz zadeklarować niestatyczne lub niekończące się pola.

rozważ użycie interfejsów, jeśli:

  1. spodziewasz się, że niepowiązane klasy zaimplementują Twój interfejs. Na przykład wiele niepowiązanych obiektów może zaimplementować interfejs Serializable.
  2. chcesz określić zachowanie określonego typu danych, ale nie przejmujesz się tym, kto implementuje jego zachowanie.
  3. Chcesz skorzystać z wielokrotne dziedziczenie typu.

Przykład:

Klasa abstrakcyjna (jest relacją )

Reader jest klasą abstrakcyjną.

BufferedReader jest Reader

FileReader jest Reader

FileReader i BufferedReader są używane do wspólnego celu: odczytu danych i są powiązane za pomocą klasy Reader.

Interface (HAS a capability )

Serializowalny jest interfejsem.

Załóżmy, że masz dwie klasy w swojej aplikacji, które implementują Serializable interfejs

Employee implements Serializable

Game implements Serializable

Tutaj nie można ustanowić żadnej relacji poprzez Serializable interfejs pomiędzy Employee i Game, które są przeznaczone do innego celu. Oba są zdolne do serializacji stanu i na tym kończy się porównanie.

Zobacz te posty:

Jak powinienem wyjaśnić różnicę między interfejsem a Zajęcia abstrakcyjne?

 25
Author: Ravindra babu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-27 14:01:51

Napisałem artykuł o tym, kiedy używać klasy abstrakcyjnej, a kiedy interfejsu. Jest między nimi o wiele więcej różnicy niż "jeden jest-A... i można-zrobić...". Dla mnie to są puszkowane odpowiedzi. Wymieniam kilka powodów, dla których warto z nich skorzystać. Mam nadzieję, że to pomoże.

Http://codeofdoom.com/wordpress/2009/02/12/learn-this-when-to-use-an-abstract-class-and-an-interface/

 10
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-12 19:19:33

1.Jeśli tworzysz coś, co zapewnia wspólną funkcjonalność niepowiązanym klasom, Użyj interfejsu.

2.Jeśli tworzysz coś dla obiektów, które są blisko powiązane w hierarchii, Użyj klasy abstrakcyjnej.

 9
Author: kuttychutty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-04 04:05:43

Klasy mogą dziedziczyć tylko z jednej klasy bazowej, więc jeśli chcesz użyć klas abstrakcyjnych do zapewnienia polimorfizmu grupie klas, wszystkie muszą dziedziczyć z tej klasy. Klasy abstrakcyjne mogą również zawierać elementy, które zostały już zaimplementowane. W związku z tym można zapewnić pewną ilość identycznej funkcjonalności z klasą abstrakcyjną, ale nie można z interfejsem.

Oto kilka zaleceń, które pomogą Ci zdecydować, czy użyć interfejsu, czy klasy abstrakcyjnej do zapewnij polimorfizm dla swoich komponentów.

  • jeśli przewidujesz utworzenie wielu wersji komponentu, Utwórz klasę abstrakcyjną. Klasy abstrakcyjne zapewniają prosty i łatwy sposób na wersję komponentów. Aktualizując klasę bazową, wszystkie klasy dziedziczące są automatycznie aktualizowane wraz ze zmianą. Z drugiej strony interfejsy nie mogą być zmieniane po utworzeniu w ten sposób. Jeśli wymagana jest nowa wersja interfejsu, musisz utworzyć zupełnie nowy interfejs.
  • Jeśli funkcjonalność, którą tworzysz, będzie przydatna w wielu różnych obiektach, Użyj interfejsu. Klasy abstrakcyjne powinny być używane przede wszystkim dla obiektów, które są ze sobą blisko powiązane, podczas gdy interfejsy najlepiej nadają się do zapewnienia wspólnej funkcjonalności niepowiązanym klasom.
  • Jeśli projektujesz małe, zwięzłe elementy funkcjonalności, użyj interfejsów. Jeśli projektujesz duże jednostki funkcjonalne, Użyj klasy abstrakcyjnej.
  • Jeśli chcesz zapewnić powszechną, zaimplementowaną funkcjonalnością spośród wszystkich implementacji twojego komponentu jest klasa abstrakcyjna. Klasy abstrakcyjne pozwalają częściowo zaimplementować klasę, podczas gdy interfejsy nie zawierają implementacji dla żadnych członków.

Skopiowane z:
http://msdn.microsoft.com/en-us/library/scsyfw1d%28v=vs.71%29.aspx

 3
Author: Mazhar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-13 08:36:08

Rozważ użycie klas abstrakcyjnych jeśli którakolwiek z tych instrukcji ma zastosowanie do twojej sytuacji:

  1. chcesz udostępnić kod między kilkoma blisko spokrewnionymi klasami.
  2. spodziewasz się, że klasy rozszerzające Twoją klasę abstrakcyjną mają wiele popularnych metod lub pól lub wymagają modyfikatorów dostępu innych niż publiczne(np. protected I private).
  3. chcesz zadeklarować niestatyczne lub niekończące się pola. Umożliwia to definiowanie metod, które mogą uzyskać dostęp i modyfikować stan przedmiot, do którego należą.

Rozważ użycie interfaces jeśli którakolwiek z tych instrukcji ma zastosowanie do twojej sytuacji:

  1. spodziewasz się, że niepowiązane klasy zaimplementują Twój interfejs. Na przykład interfejsy porównywalne i Klonowalne są implementowane przez wiele niepowiązanych klas.
  2. chcesz określić zachowanie określonego typu danych, ale nie przejmujesz się tym, kto implementuje jego zachowanie.
  3. Chcesz skorzystać z wielu spadki.

Źródło

 3
Author: Abhijeet Ashok Muneshwar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-21 07:11:02

Myślę, że najbardziej zwięzły sposób ujęcia tego jest następujący:

Dzielone właściwości = > klasa abstrakcyjna.
Współdzielona funkcjonalność = > interfejs.

I mówiąc mniej zwięźle...

Przykład Klasy Abstrakcyjnej:

public abstract class BaseAnimal
{
    public int NumberOfLegs { get; set; }

    protected BaseAnimal(int numberOfLegs)
    {
        NumberOfLegs = numberOfLegs;
    }
}

public class Dog : BaseAnimal
{
    public Dog() : base(4) { }
}

public class Human : BaseAnimal 
{
    public Human() : base(2) { }
}

Ponieważ zwierzęta mają wspólną właściwość-liczbę nóg w tym przypadku - sensowne jest utworzenie abstrakcyjnej klasy zawierającej tę wspólną właściwość. To również pozwala nam pisać wspólny kod, który działa na tej właściwości. Na przykład:

public static int CountAllLegs(List<BaseAnimal> animals)
{
    int legCount = 0;
    foreach (BaseAnimal animal in animals)
    {
        legCount += animal.NumberOfLegs;
    }
    return legCount;
}

Przykład Interfejsu:

public interface IMakeSound
{
    void MakeSound();
}

public class Car : IMakeSound
{
    public void MakeSound() => Console.WriteLine("Vroom!");
}

public class Vuvuzela : IMakeSound
{
    public void MakeSound() => Console.WriteLine("VZZZZZZZZZZZZZ!");        
}

Zauważ, że Vuvuzele i samochody to zupełnie inne rzeczy, ale mają wspólną funkcjonalność: dźwięk. Tak więc interfejs ma tu sens. Ponadto, pozwoli programistom grupować rzeczy, które wydają dźwięki w ramach wspólnego interfejsu -- IMakeSound w tym przypadku. Dzięki temu projektowi możesz napisać następujący kod:

List<IMakeSound> soundMakers = new List<ImakeSound>();
soundMakers.Add(new Car());
soundMakers.Add(new Vuvuzela());
soundMakers.Add(new Car());
soundMakers.Add(new Vuvuzela());
soundMakers.Add(new Vuvuzela());

foreach (IMakeSound soundMaker in soundMakers)
{
    soundMaker.MakeSound();
}
Możesz powiedzieć, co to da?

Wreszcie, można połącz te dwa.

Przykład Łączony:

public interface IMakeSound
{
    void MakeSound();
}

public abstract class BaseAnimal : IMakeSound
{
    public int NumberOfLegs { get; set; }

    protected BaseAnimal(int numberOfLegs)
    {
        NumberOfLegs = numberOfLegs;
    }

    public abstract void MakeSound();
}

public class Cat : BaseAnimal
{
    public Cat() : base(4) { }

    public override void MakeSound() => Console.WriteLine("Meow!");
}

public class Human : BaseAnimal 
{
    public Human() : base(2) { }

    public override void MakeSound() => Console.WriteLine("Hello, world!");
}

Tutaj wymagamy, aby wszystkie BaseAnimalwydawały dźwięk, ale nie znamy jeszcze jego realizacji. W takim przypadku możemy abstrakcyjnie zaimplementować implementację interfejsu i delegować jej implementację do podklas.

Ostatni punkt, pamiętaj, jak w przykładzie klasy abstrakcyjnej byliśmy w stanie operować na współdzielonych właściwościach różnych obiektów, a w przykładzie interfejsu byliśmy w stanie wywołać współdzieloną funkcjonalność różne przedmioty? W tym ostatnim przykładzie możemy zrobić jedno i drugie.

 3
Author: Domn Werner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-14 15:23:44

Odpowiedzi różnią się w zależności od języka. Na przykład, w Javie klasa może zaimplementować (dziedziczyć z) wiele interfejsów, ale dziedziczyć tylko z jednej klasy abstrakcyjnej. Interfejsy zapewniają większą elastyczność. Ale to nie jest prawda w C++.

 2
Author: Nick Fortescue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-26 08:55:12

Dla mnie w wielu przypadkach wybrałbym interfejsy. Ale w niektórych przypadkach wolę klasy abstrakcyjne.

Klasy w OO ogólnie odnoszą się do implementacji. Używam klas abstrakcyjnych, gdy chcę wymusić pewne szczegóły implementacji do childów, w przeciwnym razie idę z interfejsami.

Oczywiście, klasy abstrakcyjne są przydatne nie tylko w wymuszaniu implementacji, ale także w dzieleniu się pewnymi szczegółami wśród wielu powiązanych klas.

 2
Author: La VloZ Merrill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-13 20:34:21

Użyj klasy abstrakcyjnej, jeśli chcesz dostarczyć kilka podstawowych implementacji.

 1
Author: Sebastian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-26 08:48:46

W Javie można dziedziczyć z jednej (abstrakcyjnej) klasy, aby" zapewnić " funkcjonalność i można zaimplementować wiele interfejsów, aby "zapewnić" funkcjonalność

 1
Author: Peter Miehle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-26 08:52:18

czysto na podstawie dziedziczenia, użyłbyś abstraktu, w którym definiujesz wyraźnie potomka, abstrakcyjne relacje (np. zwierzę->kot) i / lub wymagałbyś dziedziczenia wirtualnych lub niepublicznych właściwości, zwłaszcza współdzielonego stanu (którego Interfejsy nie mogą obsługiwać).

Powinieneś spróbować faworyzować kompozycję (poprzez iniekcję zależności) zamiast dziedziczenia, gdzie możesz, I zauważyć, że interfejsy będące umowami wspierają Testowanie jednostek,rozdzielanie obaw i (różniące się językiem) wielokrotne dziedziczenie w sposób, w jaki abstrakcje nie mogą

 1
Author: annakata,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-26 08:56:55

Ciekawym miejscem, gdzie interfejsy radzą sobie lepiej niż klasy abstrakcyjne, jest sytuacja, w której trzeba dodać dodatkową funkcjonalność do grupy (powiązanych lub niepowiązanych) obiektów. Jeśli nie możesz dać im podstawowej klasy abstrakcyjnej (np. są sealed lub mają już rodzica), możesz dać im zamiast tego atrapy (pusty) interfejs, a następnie po prostu napisać metody rozszerzenia dla tego interfejsu.

 1
Author: Dmitri Nesteruk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-26 11:00:47

To może być bardzo trudne do wykonania...

Jeden wskaźnik mogę dać: obiekt może zaimplementować wiele interfejsów, podczas gdy obiekt może dziedziczyć tylko jedną klasę bazową(w nowoczesnym języku OO, takim jak c#, wiem, że C++ ma wiele dziedziczeń - ale czy to nie jest złe?)

 0
Author: Mesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-26 08:53:30

Klasa abstrakcyjna może mieć implementacje.

Interfejs nie ma implementacji, po prostu definiuje rodzaj umowy.

Mogą również występować pewne różnice zależne od języka: na przykład C# nie ma dziedziczenia wielokrotnego, ale wiele interfejsów może być zaimplementowanych w klasie.

 0
Author: Gerrie Schenck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-26 08:54:14

Podstawowa zasada kciuka brzmi: dla "rzeczowniki" używają klasy abstrakcyjnej , A dla "czasowniki" używają interfejsu

NP: car jest klasą abstrakcyjną i drive, możemy uczynić ją interfejsem.

 -1
Author: GANI,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-09 08:34:10