2008-11-27 18 views

Odpowiedz

20

Klasy abstrakcyjne są wykorzystywane, gdy zamierzamy stworzyć konkretną klasę, ale chcesz się upewnić, że istnieje jakiś wspólny stan we wszystkich podklas lub ewentualna wspólna realizacjadla niektórych operacji.

Interfejsy nie mogą zawierać żadnego z nich.

+0

Będę nadal definiować interfejs, nawet jeśli definiujemy klasę abstrakcyjną. Dzięki temu Twój kod jest bardziej przyjazny dla testu i mniej powiązany z konkretną implementacją. – tvanfosson

+0

Tak, oczywiście, zgadzam się na 100%. W moim kodzie zazwyczaj przypisuję interfejs do interfejsu (który brzmiał głupio) i używam klasy abstrakcyjnej jako podstawy dla standardowej implementacji i stanu. – Uri

+0

Powiedziałeś: "i użyj klasy abstrakcyjnej jako podstawy standardowej implementacji i powiedz: Prawdopodobnie miałeś na myśli: " i użyj klasy abstrakcyjnej jako podstawy dla "wspólnej implementacji" i określ " – Shaw

4

Interfejs klasy abstrakcyjnej v/s to jeden z tematów, który generuje wiele ciekawostek/zainteresowań/dezorientacji dla każdego, kto jest nowicjuszem w Javie i chce pogłębić swoją wiedzę.

This article zawiera szczegółowe wyjaśnienie tematu.

+0

Podany link był bardzo użyteczny. Daje jasne użycie zarówno abstrakcji, jak i interfejsu. – Warrior

8

Tak, istnieje miejsce zarówno dla klas abstrakcyjnych, jak i interfejsów.

Chodźmy konkretnym przykładem. Przyjrzymy się, jak utworzyć CheckingAccount i SavingsAccount z abstrakcji i zobaczyć, jak możemy użyć interfejsu odróżniającego dwa typy kont.

Aby rozpocząć, tutaj jest klasą abstrakcyjną AbstractBankAccount:

abstract class AbstractBankAccount 
{ 
    int balance; 
    public abstract void deposit(int amount); 
    public abstract void withdraw(int amount); 
} 

Mamy saldo konta balance jak i dwóch metod deposit i withdraw które muszą być wdrożone przez podklasy.

Jak widać, klasa abstrakcyjna deklaruje strukturę sposobu definiowania kont bankowych. Jak wspomina @Uri w swojej odpowiedzi, istnieje stan do tej abstrakcyjnej klasy, która jest polem balance. Nie byłoby to możliwe dzięki interfejsowi.

Teraz niech podklasa AbstractBankAccount dokonać CheckingAccount

class CheckingAccount extends AbstractBankAccount 
{ 
    public void deposit(int amount) 
    { 
     balance += amount; 
    } 

    public void withdraw(int amount) 
    { 
     balance -= amount; 
    } 
} 

W tej podklasy CheckingAccount wdrożyliśmy dwie klasy abstrakcyjne - nic zbyt ciekawy tutaj.

Jak możemy wdrożyć SavingsAccount? Różni się on od CheckingAccount tym, że zyska zainteresowanie. Oprocentowanie może zostać zwiększone za pomocą metody deposit, ale z drugiej strony nie jest to tak, jakby klient sam zdeponował zainteresowanie. Dlatego może być bardziej zrozumiałe, jeśli mamy inny sposób dodawania pieniędzy na konto, szczególnie w przypadku zainteresowania, na przykład, metodą accrueInterest.

Mogliśmy bezpośrednio wdrożyć metodę w SavingsAccount, ale możemy mieć więcej rodzajów kont bankowych, które mogą oprocentowane w przyszłości, więc możemy chcieć, aby interfejs InterestBearing który ma metodę accrueInterest:

interface InterestBearing 
{ 
    public void accrueInterest(int amount); 
} 

Więc teraz można zrobić klasę SavingsAccount które mogą zyskać zainteresowanie poprzez wdrożenie interfejsu InterestBearing:

class SavingsAccount extends AbstractBankAccount implements InterestBearing 
{ 
    public void deposit(int amount) 
    { 
     balance += amount; 
    } 

    public void withdraw(int amount) 
    { 
     balance -= amount; 
    } 

    public void accrueInterest(int amount) 
    { 
     balance += amount; 
    } 
} 

teraz, jeśli chcemy, aby anothe r typu konta, powiedzmy PremiumSavingsAccount, możemy zrobić podklasę AbstractBankAccount i wdrożyć interfejs InterestBearing, aby utworzyć inne konto oprocentowane.

Interfejs InterestBearing można zobaczyć jako , dodając wspólną funkcję do różnych klas. Nie miałoby sensu posiadanie funkcji do obsługi odsetek na kontach czekowych, gdy nie są naliczane odsetki.

Rzeczywiście istnieją miejsca, w których zarówno klasy abstrakcyjne, jak i interfejsy współistnieją i współpracują w jednej sytuacji.

0

Ogólnie interfejsy opisać publicznych API, że kod należy użyć, mając na uwadze, że abstrakcyjne klasy bazowe najlepiej zachowywać jako szczegół wdrażania, w którym można zachować wspólny kod lub państwo, aby ograniczyć powielanie w dowolnych klasach wdrażania.

Korzystając z interfejsów w swoim interfejsie API, łatwiej jest napisać kod testowy na twoich klasach, ponieważ możesz używać klas testowych, które na przykład nie zależą od zewnętrznych zasobów lub wykazują jawne rodzaje złego, ale trudnego do symulacji zachowania w rzeczywistości.

Tak Java zapewnia interfejs listy, a AbstractList abstrakcyjnej klasy bazowej do „zminimalizować wysiłek potrzebny do wdrożenia” interfejs ...

2

Istnieje kilka powodów, dla których może wolisz klasy abstrakcyjnej implementacji darmo przez interfejs:

  • Niektóre niemożliwe rzuty i operacje instanceof mogą zostać przechwycone podczas kompilacji.
  • Istnieje możliwość dodania konkretnych metod w późniejszej wersji.
  • Wiele lat temu istniała znacząca korzyść z wydajności.
  • Z bardzo niejasnej perspektywy zabezpieczeń nie można uzyskać istniejącej klasy do implementacji metod, tworząc podklasę wcześniejszej klasy i klasy abstrakcyjnej.

Ale z drugiej strony, słowo kluczowe Java interfejsu umożliwia czystsze źródło.

+0

Dziękuję pal. Podarowałeś mi cenne pomysły na moje zapytanie. – Warrior

Powiązane problemy