Jaka jest dokładnie różnica między interfejsem a klasą abstrakcyjną?
Jaka jest dokładnie różnica między interfejsem a klasą abstrakcyjną?
Odpowiedzi:
Interfejs to umowa : osoba pisząca interfejs mówi: „ hej, akceptuję rzeczy wyglądające w ten sposób ”, a osoba korzystająca z interfejsu mówi „ OK, klasa, którą piszę, wygląda w ten sposób ”.
Interfejs jest pustą powłoką . Są tylko sygnatury metod, co oznacza, że metody nie mają ciała. Interfejs nic nie może zrobić. To tylko wzór.
Na przykład (pseudo kod):
// I say all motor vehicles should look like this:
interface MotorVehicle
{
void run();
int getFuel();
}
// My team mate complies and writes vehicle looking that way
class Car implements MotorVehicle
{
int fuel;
void run()
{
print("Wrroooooooom");
}
int getFuel()
{
return this.fuel;
}
}
Wdrożenie interfejsu zużywa bardzo mało procesora, ponieważ nie jest to klasa, tylko kilka nazw, a zatem nie trzeba wykonywać żadnych kosztownych przeglądów. Jest świetny, gdy ma to znaczenie, na przykład w urządzeniach osadzonych.
Klasy abstrakcyjne, w przeciwieństwie do interfejsów, są klasami. Są one droższe w użyciu, ponieważ istnieje dziedzina, w której można je odziedziczyć.
Klasy abstrakcyjne przypominają interfejsy, ale mają coś więcej: możesz zdefiniować dla nich zachowanie. Chodzi raczej o osobę, która mówi: „ te klasy powinny tak wyglądać i mają to wspólne, więc wypełnij puste pola! ”.
Na przykład:
// I say all motor vehicles should look like this:
abstract class MotorVehicle
{
int fuel;
// They ALL have fuel, so lets implement this for everybody.
int getFuel()
{
return this.fuel;
}
// That can be very different, force them to provide their
// own implementation.
abstract void run();
}
// My teammate complies and writes vehicle looking that way
class Car extends MotorVehicle
{
void run()
{
print("Wrroooooooom");
}
}
Podczas gdy abstrakcyjne klasy i interfejsy mają być różnymi pojęciami, implementacje powodują, że to stwierdzenie jest czasami nieprawdziwe. Czasami nie są nawet tym, czym myślisz, że są.
W Javie ta zasada jest silnie egzekwowana, podczas gdy w PHP interfejsy są klasami abstrakcyjnymi bez zadeklarowanej metody.
W Pythonie klasy abstrakcyjne są bardziej sztuczką programistyczną, którą można uzyskać z modułu ABC i faktycznie używa metaklas, a zatem klas. Interfejsy są bardziej związane z pisaniem kaczek w tym języku i jest to połączenie konwencji i specjalnych metod wywołujących deskryptory (metody __method__).
Jak zwykle w przypadku programowania, istnieje teoria, praktyka i praktyka w innym języku :-)
interface
i class
od Head First Java
jest bardzo wyraźneA class defines who you are, and an interface tells what roles you could play
Kluczowe różnice techniczne między klasą abstrakcyjną a interfejsem to:
Klasy abstrakcyjne mogą mieć stałe, elementy, kody pośredniczące metod (metody bez treści) i zdefiniowane metody , podczas gdy interfejsy mogą mieć tylko stałe i kody pośredniczące metod .
Metody i elementy klasy abstrakcyjnej można zdefiniować z dowolną widocznością , podczas gdy wszystkie metody interfejsu należy zdefiniować jako public
(domyślnie są one zdefiniowane jako publiczne).
Dziedzicząc klasę abstrakcyjną, konkretna klasa potomna musi zdefiniować metody abstrakcyjne , podczas gdy klasa abstrakcyjna może rozszerzać inną klasę abstrakcyjną, a metody abstrakcyjne z klasy nadrzędnej nie muszą być definiowane.
Podobnie interfejs rozszerzający inny interfejs nie jest odpowiedzialny za implementację metod z interfejsu nadrzędnego. Wynika to z faktu, że interfejsy nie mogą zdefiniować żadnej implementacji.
Klasa podrzędna może rozszerzyć tylko jedną klasę (abstrakcyjną lub konkretną), podczas gdy interfejs może zostać rozszerzony lub klasa może zaimplementować wiele innych interfejsów .
Klasa potomna może definiować metody abstrakcyjne z taką samą lub mniej restrykcyjną widocznością , podczas gdy klasa implementująca interfejs musi definiować metody z dokładnie taką samą widocznością (publiczna).
CANNOT
są tworzone.
Interfejs zawiera tylko definicję / podpis funkcji, a jeśli mamy jakąś wspólną funkcjonalność, a także wspólne podpisy, musimy użyć klasy abstrakcyjnej. Używając klasy abstrakcyjnej, możemy zapewnić zarówno zachowanie, jak i funkcjonalność jednocześnie. Inny programista dziedziczący klasę abstrakcyjną może z łatwością korzystać z tej funkcji, ponieważ musiałby jedynie wypełnić puste pola.
http://www.dotnetbull.com/2011/11/difference-between-abstract-class-and.html
http://www.dotnetbull.com/2011/11/what-is-abstract-class-in-c-net.html http://www.dotnetbull.com/2011/11/what-is-interface-in -c-net.html
Wyjaśnienie można znaleźć tutaj: http://www.developer.com/lang/php/article.php/3604111/PHP-5-OOP-Interfaces-Abstract-Classes-and-the-Adapter-Pattern.htm
Klasa abstrakcyjna to klasa, która jest tylko częściowo implementowana przez programistę. Może zawierać jedną lub więcej metod abstrakcyjnych. Metoda abstrakcyjna jest po prostu definicją funkcji, która informuje programistę, że metoda musi zostać zaimplementowana w klasie potomnej.
Interfejs jest podobny do klasy abstrakcyjnej; w rzeczywistości interfejsy zajmują tę samą przestrzeń nazw co klasy i klasy abstrakcyjne. Z tego powodu nie można zdefiniować interfejsu o tej samej nazwie co klasa. Interfejs jest w pełni abstrakcyjną klasą; żadna z jego metod nie jest zaimplementowana i zamiast podklasy klas, mówi się, że implementuje ten interfejs.
W każdym razie to wyjaśnienie interfejsów jest nieco mylące. Częstszą definicją jest: Interfejs definiuje umowę, którą muszą spełniać klasy implementujące. Definicja interfejsu składa się z podpisów członków publicznych, bez żadnego kodu implementującego.
Nie chcę podkreślać różnic, które zostały już powiedziane w wielu odpowiedziach (dotyczących publicznych statycznych modyfikatorów końcowych dla zmiennych w interfejsie i obsługi chronionych, prywatnych metod w klasach abstrakcyjnych)
W prostych słowach chciałbym powiedzieć:
interfejs: Aby wdrożyć umowę przez wiele niepowiązanych obiektów
Klasa abstrakcyjna: Aby zaimplementować to samo lub inne zachowanie wśród wielu powiązanych obiektów
Z dokumentacji Oracle
Rozważ użycie klas abstrakcyjnych, jeśli:
Rozważ użycie interfejsów, jeśli:
Serializable
interfejs.Klasa abstrakcyjna ustanawia „jest” relacją z konkretnymi klasami. interfejs zapewnia możliwość „klas” dla klas.
Jeśli szukasz Java
jako języka programowania, oto kilka innych aktualizacji:
Java 8 w pewnym stopniu zmniejszyła lukę między klasami interface
i abstract
udostępniając funkcję default
metody. Interfejs nie ma implementacji dla metody, która nie jest już poprawna.
Więcej informacji można znaleźć na tej stronie dokumentacji .
Spójrz na to pytanie SE, aby znaleźć przykłady kodu, aby lepiej zrozumieć.
Jak powinienem wyjaśnić różnicę między interfejsem a klasą abstrakcyjną?
Kilka ważnych różnic:
W formie tabeli:
Jak stwierdził Joe z javapapers :
1. Główna różnica polega na tym, że metody interfejsu Java są domyślnie abstrakcyjne i nie mogą mieć implementacji. Klasa abstrakcyjna Java może mieć metody instancji, które implementują domyślne zachowanie.
2. Zmienne zadeklarowane w interfejsie Java są domyślnie ostateczne. Klasa abstrakcyjna może zawierać nie-końcowe zmienne.
3. Członkowie interfejsu Java są domyślnie publiczni. Klasa abstrakcyjna Java może mieć zwykłe smaki członków klasy, takie jak prywatny, chroniony itp.
4. Interfejs Java powinien zostać zaimplementowany przy użyciu słowa kluczowego „implements”; Klasa abstrakcyjna Java powinna zostać rozszerzona za pomocą słowa kluczowego „extends”.
5. Interfejs może rozszerzyć tylko inny interfejs Java, klasa abstrakcyjna może rozszerzyć inną klasę Java i zaimplementować wiele interfejsów Java.
6. Klasa Java może implementować wiele interfejsów, ale może rozszerzać tylko jedną klasę abstrakcyjną.
7. Interfejs jest absolutnie abstrakcyjny i nie można go tworzyć; Nie można również utworzyć instancji klasy abstrakcyjnej Java, ale można ją wywołać, jeśli istnieje main ().
8. W porównaniu z klasami abstrakcyjnymi Java, interfejsy Java są wolne, ponieważ wymaga dodatkowej pośredniczenia.
Najważniejsze jest to, że:
Buduję budynek o 300 piętrach
Interfejs projektu budynku
Budynek zbudowany do 200 pięter - częściowo ukończony --- streszczenie
Konstrukcja budynku zakończona - beton
Berło
Abstrakcyjny
Zaczerpnięte ze strony internetowej DurgaJobs
Ponownie popracujmy nad tym pytaniem:
Pierwszą rzeczą, którą należy poinformować, jest to, że wyniki 1/1 i 1 * 1 dają to samo, ale nie oznacza to, że mnożenie i dzielenie są takie same. Oczywiście utrzymują dobre relacje, ale pamiętajcie, że oboje jesteście inni.
Wskażę główne różnice, a pozostałe zostały już wyjaśnione:
Klasy abstrakcyjne są przydatne do modelowania hierarchii klas. Na pierwszy rzut oka na każde wymaganie, częściowo wiemy, co dokładnie ma być zbudowane, ale wiemy, co zbudować. Tak więc twoje abstrakcyjne klasy są twoimi klasami podstawowymi.
Interfejsy są przydatne, aby umożliwić innym hierarchom lub klasom wiedzieć, co jestem w stanie zrobić. A kiedy mówisz, że jestem zdolny do czegoś, musisz mieć taką zdolność. Interfejsy oznaczą to jako obowiązkowe, aby klasa mogła wdrożyć te same funkcje.
Właściwie to całkiem proste.
Możesz myśleć o interfejsie jako o klasie, która może mieć tylko abstrakcyjne metody i nic więcej.
Interfejs może więc tylko „zadeklarować” i nie definiować zachowania, które ma mieć klasa.
Klasa abstrakcyjna pozwala zarówno zadeklarować (przy użyciu metod abstrakcyjnych), jak i zdefiniować (przy użyciu pełnych implementacji metod) zachowanie, które ma mieć klasa.
A zwykła klasa pozwala tylko definiować, a nie deklarować zachowanie / działania, które ma mieć klasa.
Ostatnia rzecz,
W Javie możesz zaimplementować wiele interfejsów, ale możesz rozszerzyć tylko jeden (Klasa abstrakcyjna lub Klasa) ...
Oznacza to, że dziedziczenie zdefiniowanego zachowania jest ograniczone, aby zezwolić tylko na jedną na klasę ... tzn. Jeśli chciałbyś, aby klasa obejmowała zachowanie z klas A, B i C, musisz wykonać następujące czynności: Klasa A rozszerza B, klasa C rozszerza A. to trochę okrągły sposób na wielokrotne dziedziczenie ...
Z drugiej strony interfejsy można po prostu zrobić: interfejs C implementuje A, B
W efekcie Java obsługuje wielokrotne dziedziczenie tylko w „zadeklarowanym zachowaniu”, tj. Interfejsach, i tylko pojedyncze dziedziczenie ze zdefiniowanym zachowaniem. O ile nie zrobisz tego w sposób opisany ...
Mam nadzieję, że to ma sens.
Porównanie interfejsu z klasą abstrakcyjną jest nieprawidłowe. Zamiast tego powinny być dwa inne porównania: 1) interfejs vs. klasa i 2) abstrakcja vs. klasa ostateczna .
Interfejs to umowa między dwoma obiektami. Np. Jestem listonoszem, a ty paczką do dostarczenia. Oczekuję, że znasz swój adres dostawy. Kiedy ktoś daje mi Paczkę, musi znać jej adres dostawy:
interface Package {
String address();
}
Klasa to grupa obiektów zgodnych z umową. Np. Jestem skrzynką z grupy „Box” i przestrzegam kontraktu wymaganego przez Listonosza. Jednocześnie przestrzegam innych umów:
class Box implements Package, Property {
@Override
String address() {
return "5th Street, New York, NY";
}
@Override
Human owner() {
// this method is part of another contract
}
}
Klasa abstrakcyjna to grupa niekompletnych obiektów. Nie można ich użyć, ponieważ brakuje niektórych części. Na przykład jestem abstrakcyjnym pudełkiem obsługującym GPS - wiem, jak sprawdzić swoją pozycję na mapie:
abstract class GpsBox implements Package {
@Override
public abstract String address();
protected Coordinates whereAmI() {
// connect to GPS and return my current position
}
}
Ta klasa, jeśli zostanie odziedziczona / rozszerzona przez inną klasę, może być bardzo przydatna. Ale sam w sobie - jest bezużyteczny, ponieważ nie może mieć przedmiotów. Klasy abstrakcyjne mogą być elementami budującymi klasy końcowe.
Ostateczna klasa to grupa kompletnych obiektów, których można używać, ale nie można ich modyfikować. Wiedzą dokładnie, jak pracować i co robić. Na przykład jestem skrzynką, która zawsze idzie na adres podany podczas jej budowy:
final class DirectBox implements Package {
private final String to;
public DirectBox(String addr) {
this.to = addr;
}
@Override
public String address() {
return this.to;
}
}
W większości języków, takich jak Java lub C ++, można mieć tylko klasę , ani abstrakcyjnej, ani końcowej. Taką klasę można odziedziczyć i utworzyć jej instancję. Nie sądzę jednak, aby było to ściśle zgodne z paradygmatem obiektowym.
Ponownie porównanie interfejsów z klasami abstrakcyjnymi jest nieprawidłowe.
W skrócie różnice są następujące:
Różnice składniowe między interfejsem a klasą abstrakcyjną :
Teraz w interfejsach:
public static
- obsługiwane - obsługiwane
public abstract
- obsługiwane
public default
- obsługiwane
private static
- obsługiwane
private abstract
- błąd
private default
kompilacji
private
- błąd kompilacji - obsługiwane
Jedyna różnica polega na tym, że jeden może uczestniczyć w wielokrotnym dziedziczeniu, a drugi nie.
Definicja interfejsu zmieniła się z czasem. Czy uważasz, że interfejs ma tylko deklaracje metod i są tylko umowami? Co ze statycznymi zmiennymi końcowymi, a co z definicjami domyślnymi po Javie 8?
Interfejsy zostały wprowadzone do Javy ze względu na problem diamentów z wielokrotnym dziedziczeniem i właśnie to zamierzają zrobić.
Interfejsy to konstrukcje utworzone w celu uniknięcia problemu wielokrotnego dziedziczenia, które mogą zawierać metody abstrakcyjne, definicje domyślne i statyczne zmienne końcowe.
Interfejs: Skręć (skręć w lewo, skręć w prawo.)
Klasa abstrakcyjna: koło.
Klasa: Kierownica, wywodzi się z koła, odsłania zakręt interfejsu
Jednym z nich jest kategoryzowanie zachowań, które można zaoferować w odniesieniu do różnych przedmiotów, a drugim - modelowanie ontologii rzeczy.
Jeśli masz kilka typowych metod, które mogą być używane przez wiele klas, przejdź do klas abstrakcyjnych. Jeśli chcesz, aby klasy postępowały zgodnie z określonym schematem, wybierz interfejsy.
Poniższe przykłady pokazują to.
Klasa abstrakcyjna w Javie:
abstract class animals
{
// They all love to eat. So let's implement them for everybody
void eat()
{
System.out.println("Eating...");
}
// The make different sounds. They will provide their own implementation.
abstract void sound();
}
class dog extends animals
{
void sound()
{
System.out.println("Woof Woof");
}
}
class cat extends animals
{
void sound()
{
System.out.println("Meoww");
}
}
Poniżej przedstawiono implementację interfejsu w Javie:
interface Shape
{
void display();
double area();
}
class Rectangle implements Shape
{
int length, width;
Rectangle(int length, int width)
{
this.length = length;
this.width = width;
}
@Override
public void display()
{
System.out.println("****\n* *\n* *\n****");
}
@Override
public double area()
{
return (double)(length*width);
}
}
class Circle implements Shape
{
double pi = 3.14;
int radius;
Circle(int radius)
{
this.radius = radius;
}
@Override
public void display()
{
System.out.println("O"); // :P
}
@Override
public double area()
{
return (double)((pi*radius*radius)/2);
}
}
Kilka ważnych kluczowych punktów w skrócie:
Zmienne zadeklarowane w interfejsie Java są domyślnie ostateczne. Klasy abstrakcyjne mogą mieć nie-końcowe zmienne.
Zmienne zadeklarowane w interfejsie Java są domyślnie statyczne. Klasy abstrakcyjne mogą mieć zmienne niestatyczne.
Członkowie interfejsu Java są domyślnie publiczni. Klasa abstrakcyjna Java może mieć zwykłe smaki członków klasy, takie jak prywatny, chroniony itp.
Wielu młodszych programistów popełnia błąd, uważając interfejsy, klasy abstrakcyjne i konkretne za niewielkie odmiany tego samego, i wybiera jeden z nich wyłącznie ze względów technicznych: Czy potrzebuję wielokrotnego dziedziczenia? Czy potrzebuję miejsca, aby zastosować wspólne metody? Czy muszę zawracać sobie głowę czymś innym niż konkretną klasą? Jest to błędne i ukryty w tych pytaniach jest główny problem: „ja” . Pisząc kod dla siebie, rzadko myślisz o innych obecnych lub przyszłych programistach pracujących nad tym kodem lub z nim.
Interfejsy i klasy abstrakcyjne, choć pozornie podobne z technicznego punktu widzenia, mają zupełnie inne znaczenia i cele.
Interfejs definiuje umowę, którą zrealizuje dla Ciebie niektóre wdrożenie .
Klasa abstrakcyjna zapewnia domyślne zachowanie, którego implementacja może ponownie użyć.
Konkretna klasa wykonuje konkretną pracę w bardzo specyficzny sposób. Na przykład, ArrayList
wykorzystuje ciągły obszar pamięci do przechowywania listy obiektów w zwarty sposób, który oferuje szybki losowy dostęp, iterację i zmiany w miejscu, ale jest straszny przy wstawianiu, usuwaniu, a czasem nawet dodawaniu; w międzyczasieLinkedList
wykorzystuje podwójnie połączone węzły do przechowywania listy obiektów, która zamiast tego oferuje szybką iterację, zmiany w miejscu oraz wstawianie / usuwanie / dodawanie, ale jest straszna przy przypadkowym dostępie. Te dwa typy list są zoptymalizowane pod kątem różnych przypadków użycia i bardzo ważne jest, jak je wykorzystasz. Kiedy próbujesz wycisnąć wydajność z listy, z którą intensywnie wchodzisz w interakcję, i gdy wybór rodzaju listy zależy od ciebie, powinieneś ostrożnie wybrać, który z nich tworzysz.
Z drugiej strony, użytkownicy wysokiego poziomu listy tak naprawdę nie dbają o to, jak jest ona faktycznie implementowana i powinni być odizolowani od tych szczegółów. Wyobraźmy sobie, że Java nie ujawnia List
interfejsu, ale ma tylko konkretną List
klasę, która jest właśnie tym, co LinkedList
jest teraz. Wszyscy programiści Java dostosowaliby swój kod do szczegółów implementacji: unikaj losowego dostępu, dodaj pamięć podręczną, aby przyspieszyć dostęp, lub po prostu dokonaj ponownej implementacji ArrayList
samodzielnie, chociaż byłoby to niezgodne z całym innym kodem, który faktycznie działa zList
tylko . To byłoby okropne ... Ale teraz wyobraź sobie, że mistrzowie Javy faktycznie zdają sobie sprawę, że połączona lista jest okropna w większości rzeczywistych przypadków użycia, i postanowili przełączyć się na listę tablic tylko dla siebieList
klasa dostępna. Wpłynęłoby to na wydajność każdego programu Java na świecie i ludzie nie byliby z tego powodu zadowoleni. A głównym winowajcą jest to, że szczegóły implementacji były dostępne, a programiści założyli, że są to stałe umowy, na których mogą polegać. Dlatego ważne jest, aby ukryć szczegóły implementacji i zdefiniować tylko abstrakcyjną umowę. Jest to cel interfejsu: zdefiniowanie, jakiego rodzaju dane wejściowe akceptuje metoda i jakiego rodzaju danych wyjściowych oczekuje się, bez ujawniania wszystkich odwagi, która skusiłaby programistów do poprawienia kodu w celu dopasowania do wewnętrznych szczegółów, które mogą ulec zmianie przy każdej przyszłej aktualizacji .
Klasa abstrakcyjna znajduje się pośrodku między interfejsami a konkretnymi klasami. Ma to pomóc implementacjom we wspólnym lub nudnym kodzie. Na przykład, AbstractCollection
zapewnia, że podstawowe implementacje isEmpty
oparte na rozmiarze są contains
równe 0, gdy iterują i porównują, addAll
jak powtórzono add
itd. Pozwala to implementacjom skoncentrować się na kluczowych elementach, które je odróżniają: jak faktycznie przechowywać i odzyskiwać dane.
Interfejsy są bramami o niskiej spójności między różnymi częściami kodu. Pozwalają one na istnienie i ewolucję bibliotek bez rozbijania każdego użytkownika biblioteki, gdy coś zmienia się wewnętrznie. To się nazywa interfejs programowania aplikacji , a nie klasy programowania aplikacji. Na mniejszą skalę pozwalają także wielu programistom z powodzeniem współpracować przy projektach na dużą skalę, oddzielając różne moduły za pomocą dobrze udokumentowanych interfejsów.
Klasy abstrakcyjne są pomocnikami o wysokiej spójności, które można stosować podczas implementacji interfejsu, przy założeniu pewnego poziomu szczegółów implementacji. Alternatywnie klasy abstrakcyjne są używane do definiowania SPI, interfejsów dostawcy usług.
Różnica między interfejsem API a interfejsem SPI jest subtelna, ale ważna: w przypadku interfejsu API skupia się na tym, kto go używa , aw przypadku interfejsu SPI koncentruje się na tym, kto go implementuje .
Dodawanie metod do interfejsu API jest łatwe, wszyscy obecni użytkownicy interfejsu API będą się nadal kompilować. Dodawanie metod do SPI jest trudne, ponieważ każdy dostawca usług (konkretne wdrożenie) będzie musiał wdrożyć nowe metody. Jeśli interfejsy są używane do definiowania SPI, dostawca będzie musiał wydać nową wersję za każdym razem, gdy zmieni się umowa SPI. Jeśli zamiast tego zostaną użyte klasy abstrakcyjne, nowe metody można zdefiniować w kategoriach istniejących metod abstrakcyjnych lub jako puste throw not implemented exception
kody pośredniczące, co pozwoli przynajmniej kompilować i uruchamiać starszą wersję implementacji usługi.
Chociaż Java 8 wprowadziła domyślne metody interfejsów, co sprawia, że linia między interfejsami a klasami abstrakcyjnymi jest jeszcze bardziej rozmyta, nie było to tak, że implementacje mogą ponownie wykorzystywać kod, ale aby ułatwić zmianę interfejsów, które służą zarówno jako interfejs API, jak i SPI (lub są niewłaściwie używane do definiowania SPI zamiast klas abstrakcyjnych).
Następstwo: odwrotnie jest często źle robione: używając czegoś , zawsze staraj się używać najbardziej ogólnej klasy / interfejsu, którego naprawdę potrzebujesz. Innymi słowy, nie deklaruj zmiennych jako ArrayList theList = new ArrayList()
, chyba że faktycznie masz bardzo silną zależność od tego, że jest to lista tablic i żaden inny typ listy nie wyciąłby jej za ciebie. Użyj List theList = new ArrayList
zamiast tego, a nawet Collection theCollection = new ArrayList
jeśli fakt, że jest to lista, a nie jakikolwiek inny rodzaj kolekcji, nie ma znaczenia.
Naprawdę nie jest to odpowiedź na pierwotne pytanie, ale kiedy już znajdziesz odpowiedź na różnicę między nimi, wejdziesz w dylemat „ kiedy używać” : kiedy używać interfejsów lub klas abstrakcyjnych? Kiedy używać obu?
Mam ograniczoną wiedzę na temat OOP, ale do tej pory sprawdzanie interfejsów jako odpowiednika przymiotnika w gramatyce (popraw mnie, jeśli ta metoda jest fałszywa!). Na przykład nazwy interfejsów są jak atrybuty lub funkcje, które można nadać klasie, a klasa może mieć wiele z nich: ISerializable, ICountable, IList, ICacheable, IHappy, ...
Dziedziczenie służy dwóm celom:
Aby obiekt mógł traktować elementy danych typu macierzystego i implementacje metod jako własne.
Aby umożliwić odwołanie do obiektów jednego typu przez kod, który oczekuje odwołania do obiektu nadtypu.
W językach / frameworkach, które obsługują uogólnione wielokrotne dziedziczenie, często nie ma potrzeby klasyfikowania typu jako „interfejsu” lub „klasy abstrakcyjnej”. Jednak popularne języki i frameworki pozwolą typowi traktować elementy danych jednego typu lub implementacje metod jako własne, mimo że pozwalają one na zamianę typu na dowolną liczbę innych typów.
Klasy abstrakcyjne mogą mieć elementy danych i implementacje metod, ale mogą być dziedziczone tylko przez klasy, które nie dziedziczą z żadnych innych klas. Interfejsy nie nakładają prawie żadnych ograniczeń na typy, które je implementują, ale nie mogą zawierać żadnych elementów danych ani implementacji metod.
Są chwile, w których użyteczne jest zastępowanie typów wieloma różnymi rzeczami; zdarzają się sytuacje, w których obiekty mogą traktować elementy danych typu macierzystego i implementacje metod jako własne. Dokonanie rozróżnienia między interfejsami a klasami abstrakcyjnymi pozwala na użycie każdej z tych umiejętności w przypadkach, gdy jest to najbardziej istotne.
Kluczowe punkty:
Korzyść:
znajdź szczegóły tutaj ... http://pradeepatkari.wordpress.com/2014/11/20/interface-and-abstract-class-in-c-oops/
Najkrótszym sposobem na podsumowanie jest to, że an interface
:
default
i static
metody; chociaż ma definicje (podpisy metod + implementacje) default
i static
metody, ma tylko deklaracje (podpisy metod) dla innych metod.interface
s, a interface
może dziedziczyć z wielu interface
s). Wszystkie zmienne są domyślnie stałe, niezależnie od tego, czy są określone jako public static final
czy nie. Wszyscy członkowie są domyślnie public
, niezależnie od tego, czy są określeni jako tacy, czy nie.Tymczasem abstract
klasa to:
abstract
metod. Może zawierać zarówno deklaracje, jak i definicje, z deklaracjami oznaczonymi jakoabstract
.protected
, private
lub pakiet prywatnej (nieokreślony).Lub, jeśli chcemy gotować to wszystko na jednym zdaniu: AN interface
co klasa wykonania ma , ale abstract
klasa jest co podklasa jest .
Chciałbym dodać jeszcze jedną różnicę, która ma sens. Na przykład masz strukturę z tysiącami wierszy kodu. Teraz, jeśli chcesz dodać nową funkcję w całym kodzie za pomocą metody enhUI (), lepiej jest dodać tę metodę w klasie abstrakcyjnej, a nie w interfejsie. Ponieważ jeśli dodasz tę metodę do interfejsu, powinieneś ją zaimplementować we wszystkich zaimplementowanych klasach, ale nie jest tak w przypadku dodania metody w klasie abstrakcyjnej.
Aby dać prostą, ale jasną odpowiedź, pomaga ustawić kontekst: używasz obu, gdy nie chcesz zapewniać pełnych implementacji.
Główną różnicą jest to, że interfejs nie ma żadnej implementacji (tylko metody bez treści), podczas gdy klasy abstrakcyjne mogą mieć również elementy i metody z treścią, tzn. Mogą być częściowo implementowane.
default
słowa kluczowego w Javie 8, za pomocą którego możesz również zdefiniować konkretne metody w interfejsach.
Różnice między klasą abstrakcyjną a interfejsem w imieniu rzeczywistej implementacji.
Berło : Jest to słowo kluczowe i służy do zdefiniowania szablonu lub niebieskiego wydruku obiektu i wymusza, aby wszystkie podklasy podążały za tym samym prototypem, ponieważ w przypadku implementacji wszystkie podklasy mogą implementować funkcjonalność zgodnie z to wymóg.
Niektóre inne przypadki użycia, w których powinniśmy użyć interfejsu.
Komunikacja między dwoma obiektami zewnętrznymi (integracja strony trzeciej w naszej aplikacji) odbywa się za pośrednictwem interfejsu tutaj Interfejs działa jako umowa.
Klasa abstrakcyjna: streszczenie, jest słowem kluczowym, a kiedy używamy tego słowa kluczowego przed jakąkolwiek klasą, staje się klasą abstrakcyjną. Jest używana głównie, gdy musimy zdefiniować szablon, a także niektóre domyślne funkcje obiektu, po którym następuje podklasy, w ten sposób usuwa zbędny kod i jeszcze jeden przypadek użycia, w którym możemy użyć klasy abstrakcyjnej , ponieważ nie chcemy, aby inne klasy mogły bezpośrednio tworzyć instancję obiektu klasy, tylko klasy pochodne mogą korzystać z tej funkcji.
Przykład klasy abstrakcyjnej:
public abstract class DesireCar
{
//It is an abstract method that defines the prototype.
public abstract void Color();
// It is a default implementation of a Wheel method as all the desire cars have the same no. of wheels.
// and hence no need to define this in all the sub classes in this way it saves the code duplicasy
public void Wheel() {
Console.WriteLine("Car has four wheel");
}
}
**Here is the sub classes:**
public class DesireCar1 : DesireCar
{
public override void Color()
{
Console.WriteLine("This is a red color Desire car");
}
}
public class DesireCar2 : DesireCar
{
public override void Color()
{
Console.WriteLine("This is a red white Desire car");
}
}
Przykład interfejsu:
public interface IShape
{
// Defines the prototype(template)
void Draw();
}
// All the sub classes follow the same template but implementation can be different.
public class Circle : IShape
{
public void Draw()
{
Console.WriteLine("This is a Circle");
}
}
public class Rectangle : IShape
{
public void Draw()
{
Console.WriteLine("This is a Rectangle");
}
}
Można znaleźć wyraźną różnicę między interfejsem a klasą abstrakcyjną.
Berło
Klasa abstrakcyjna
Klasa abstrakcyjna zawiera metody abstrakcyjne i nieabstrakcyjne.
Nie zmusza użytkowników do implementacji wszystkich metod po odziedziczeniu klasy abstrakcyjnej.
Zawiera wszystkie rodzaje zmiennych, w tym prymitywne i nieprymitywne
Zadeklaruj za pomocą abstrakcyjnego słowa kluczowego.
Metody i elementy klasy abstrakcyjnej można definiować z dowolną widocznością.
Klasa podrzędna może rozszerzyć tylko jedną klasę (abstrakcyjną lub konkretną).
Klasa abstrakcyjna to klasa, której obiektu nie można utworzyć, lub klasa, której nie można utworzyć. Metoda abstrakcyjna czyni klasę abstrakcyjną. Klasa abstrakcyjna musi zostać odziedziczona, aby zastąpić metody zadeklarowane w klasie abstrakcyjnej. Brak ograniczeń dotyczących specyfikatorów dostępu. Klasa abstrakcyjna może zawierać w sobie konstruktor i inne konkretne metody (nie-abstarct), ale interfejs nie może.
Interfejs to schemat / szablon metod (np. Podany jest dom na papierze (interfejs domu), a różni architekci wykorzystają swoje pomysły do jego zbudowania (klasy architektów wdrażających interfejs domu). Jest to zbiór metody abstrakcyjne, metody domyślne, metody statyczne, zmienne końcowe i klasy zagnieżdżone. Wszyscy członkowie będą ostateczni lub publiczni, specyfikatory dostępu chronionego i prywatnego są niedozwolone. Nie można tworzyć obiektów. Klasa musi być stworzona w celu użycia implementuje interfejs, a także zastępuje metodę abstrakcyjną zadeklarowaną w interfejsie. Interfejs jest dobrym przykładem luźnego sprzężenia (dynamiczny polimorfizm / dynamiczne wiązanie) Interfejs implementuje polimorfizm i abstrakcję. Mówi, co robić, ale jak to zrobić, jest zdefiniowane przez klasa implementacyjna, np. tam ”jest firmą samochodową i chce, aby niektóre funkcje były takie same dla wszystkich samochodów, które produkuje, dlatego firma stworzyłaby interfejs, który będzie posiadał te cechy i różne klasy samochodów (takie jak Maruti Suzkhi, Maruti 800) zastąpią te funkcje (funkcje).
Po co interfejs, skoro mamy już klasę abstrakcyjną? Java obsługuje tylko dziedziczenie wielopoziomowe i hierarchiczne, ale za pomocą interfejsu możemy zaimplementować wielokrotne dziedziczenie.
W praktyce (JAVA), główna różnica między klasą abstrakcyjną a interfejsem polega na tym, że klasa abstrakcyjna może utrzymać stan. Oprócz stanu wstrzymania możemy również wykonywać operacje spoczynku za pomocą interfejsu.
W interfejsie wszystkie metody muszą być tylko definicjami, nie należy implementować pojedynczej.
Ale w klasie abstrakcyjnej musi istnieć metoda abstrakcyjna z tylko definicją, ale inne metody mogą być również w klasie abstrakcyjnej z implementacją ...
Mamy różne różnice strukturalne / składniowe między interfejsem a klasą abstrakcyjną. Są jeszcze inne różnice
[1] Różnica oparta na scenariuszu :
Klasy abstrakcyjne są używane w scenariuszach, w których chcemy ograniczyć użytkownika do tworzenia obiektu klasy nadrzędnej ORAZ uważamy, że w przyszłości zostanie dodanych więcej metod abstrakcyjnych.
Interfejs musi być użyty, gdy jesteśmy pewni, że nie będzie już więcej abstrakcyjnej metody do dostarczenia. Następnie publikowany jest tylko interfejs.
[2] Różnica koncepcyjna :
„Czy w przyszłości będziemy musieli zapewnić więcej abstrakcyjnych metod”, jeśli TAK sprawi, że będzie to klasa abstrakcyjna, a jeśli NIE sprawi, że będzie to interfejs?
(Najbardziej odpowiedni i ważny do java 1.7)
zwykle Klasa abstrakcyjna używana do rdzenia czegoś, ale interfejs używany do dołączania urządzeń peryferyjnych.
gdy chcesz utworzyć typ podstawowy dla pojazdu, powinieneś użyć klasy abstrakcyjnej, ale jeśli chcesz dodać funkcjonalność lub właściwość, która nie jest częścią podstawowej koncepcji pojazdu, powinieneś użyć interfejsu, na przykład chcesz dodać funkcję „ToJSON ()” .
interfejs ma szeroki zakres abstrakcji zamiast abstrakcyjnej klasy. możesz to zobaczyć przekazując argumenty. spójrz na ten przykład:
jeśli użyjesz pojazdu jako argumentu, możesz po prostu użyć jednego z jego pochodnych typów (autobus lub pojazd tej samej kategorii, tylko kategoria pojazdu). ale kiedy używasz interfejsu IMoveable jako argumentu, masz więcej możliwości.