Ciekawa rzecz dzieje się w Javie, gdy używasz klasy abstrakcyjnej do implementacji interfejsu: może brakować niektórych metod interfejsu (tj. Nie ma ani abstrakcyjnej deklaracji, ani rzeczywistej implementacji), ale kompilator nie narzeka.
Na przykład, biorąc pod uwagę interfejs:
public interface IAnything {
void m1();
void m2();
void m3();
}
Następująca klasa abstrakcyjna zostaje radośnie skompilowana bez ostrzeżenia lub błędu:
public abstract class AbstractThing implements IAnything {
public void m1() {}
public void m3() {}
}
Czy możesz mi wytłumaczyć dlaczego?
java
interface
abstract-class
Giulio Piancastelli
źródło
źródło
:w
z plików.Odpowiedzi:
Dzieje się tak, ponieważ jeśli klasa jest abstrakcyjna, to z definicji wymagane jest utworzenie jej podklas w celu utworzenia instancji. Podklasy będą wymagane (przez kompilator) do zaimplementowania wszelkich metod interfejsu, które pominęła klasa abstrakcyjna.
Postępując zgodnie z przykładowym kodem, spróbuj utworzyć podklasę
AbstractThing
bez implementowaniam2
metody i zobacz, jakie błędy daje kompilator. Zmusi Cię to do wdrożenia tej metody.źródło
Całkiem w porządku.
Nie można utworzyć instancji klas abstrakcyjnych ... ale klasy abstrakcyjne mogą służyć do przechowywania typowych implementacji dla m1 () i m3 ().
Więc jeśli implementacja m2 () jest inna dla każdej implementacji, ale m1 i m3 nie. Możesz tworzyć różne konkretne implementacje IAnything tylko z inną implementacją m2 i czerpać z AbstractThing - z poszanowaniem zasady DRY. Sprawdzanie, czy interfejs jest całkowicie zaimplementowany dla klasy abstrakcyjnej, jest daremne.
Aktualizacja : Co ciekawe, uważam, że C # wymusza to jako błąd kompilacji. W tym scenariuszu musisz skopiować sygnatury metod i poprzedzić je „abstract public” w abstrakcyjnej klasie bazowej .. (codziennie coś nowego :)
źródło
W porządku. Aby zrozumieć powyższe, musisz najpierw zrozumieć naturę klas abstrakcyjnych. Pod tym względem są podobne do interfejsów. Oto, co o tym tutaj mówi Oracle .
Musisz więc pomyśleć o tym, co się stanie, gdy interfejs rozszerzy inny interfejs. Na przykład ...
... jak widać, kompiluje się to również doskonale. Po prostu dlatego, że podobnie jak w przypadku klasy abstrakcyjnej NIE można utworzyć wystąpienia interfejsu. Dlatego nie jest wymagane jawne wymienianie metod z jego „rodzica”. Jednak WSZYSTKIE sygnatury metod nadrzędnych niejawnie stają się częścią rozszerzającego interfejsu lub implementującej klasy abstrakcyjnej. Tak więc, gdy odpowiednia klasa (taka, która może zostać utworzona) rozszerzy powyższe, będzie wymagane upewnienie się, że każda metoda abstrakcyjna zostanie zaimplementowana.
Mam nadzieję, że to pomoże ... i Allahu 'alam!
źródło
Interfejs oznacza klasę, która nie ma implementacji swojej metody, ale ma tylko deklarację.
Z drugiej strony, klasa abstrakcyjna to klasa, która może mieć implementację pewnej metody razem z jakąś metodą z samą deklaracją, bez implementacji.
Kiedy implementujemy interfejs do klasy abstrakcyjnej, oznacza to, że klasa abstrakcyjna odziedziczyła wszystkie metody interfejsu. Ponieważ implementacja całej metody w klasie abstrakcyjnej nie jest ważna, jednak chodzi o klasę abstrakcyjną (również przez dziedziczenie), więc klasa abstrakcyjna może pozostawić część metody w interfejsie bez implementacji tutaj. Ale kiedy ta klasa abstrakcyjna zostanie odziedziczona przez jakąś konkretną klasę, muszą zaimplementować wszystkie te niezaimplementowane metody w klasie abstrakcyjnej.
źródło
Biorąc pod uwagę interfejs:
Tak naprawdę widzi to Java:
Możesz więc pozostawić niektóre (lub wszystkie) z tych
abstract
metod niezaimplementowanych, tak jak zrobiłbyś to w przypadkuabstract
klas rozszerzających innąabstract
klasę.Kiedy , reguła, że wszystkie metody muszą być wdrożone w pochodny , odnosi się tylko do konkretnej realizacji (tj, która nie jest sama w sobie).
implement
interface
interface
class
class
abstract
Jeśli rzeczywiście planujesz stworzyć
abstract class
wyjście z tego, nie ma reguły, która mówi, że masz doimplement
wszystkichinterface
metod (pamiętaj, że w takim przypadku obowiązkowe jest zadeklarowanie pochodnejclass
jakoabstract
)źródło
javap IAnything.class
do wygenerowania drugiego fragmentu kodu.Źródła: http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
źródło
Do implementacji metod nie są wymagane klasy abstrakcyjne. Więc nawet jeśli implementuje interfejs, abstrakcyjne metody interfejsu mogą pozostać abstrakcyjne. Jeśli spróbujesz zaimplementować interfejs w konkretnej klasie (tj. Nie abstrakcyjnej) i nie zaimplementujesz metod abstrakcyjnych, kompilator powie ci: albo zaimplementuj metody abstrakcyjne, albo zadeklaruj klasę jako abstrakcyjną.
źródło