2016-03-14 15 views
27

Załóżmy, że mam czystą abstrakcyjną klasę (czyli klasa abstrakcyjna bez realizacji):Rozszerzanie vs. wdrożenie czystej klasy abstrakcyjnej w maszynopisie

abstract class A { 
    abstract m(): void; 
} 

Podobnie jak w C# i Java, mogę przedłużyć abstrakcyjna klasa:

class B extends A { 
    m(): void { } 
} 

Ale przeciwieństwie w C# i Java, mogę również wdrożyć abstrakcyjną klasę:

class C implements A { 
    m(): void { } 
} 

Jak zrobić klas B i C zachowują się inaczej? Dlaczego wybrałbym jeden kontra drugi?

(Obecnie maszynopis handbook i language specification nie obejmują klas abstrakcyjnych.)

+0

Istnieje teraz rozdział poświęcony klasom abstrakcyjnym w podręczniku TypeScript. https://www.typescriptlang.org/docs/handbook/classes.html Dziękuję za to pytanie! Nie miałem pojęcia, że ​​"streszczenie" było dostępne w TS i to pomogło mi to zrozumieć. – theUtherSide

Odpowiedz

33

realizuje słowa kluczowego traktuje klasy jako interfejs, co oznacza C musi wdrożyć wszystkie metody zdefiniowane w, bez względu na to, czy mają implementację, czy nie, w A. Również nie ma połączeń z super metodami w C.

rozszerza się o zachowuje się bardziej jak to, czego można oczekiwać od słowa kluczowego. Trzeba zaimplementować tylko metody abstrakcyjne, a supełki są dostępne/generowane.

Sądzę, że w przypadku metod abstrakcyjnych nie ma to znaczenia. Ale rzadko masz klasę klasy tylko z metodami abstrakcyjnymi, jeśli to zrobisz, znacznie lepiej byłoby po prostu przekształcić ją w interfejs .

Możesz to łatwo zobaczyć, patrząc na wygenerowany kod. Zrobiłem przykład placu zabaw here.

+3

Jeśli "A" jest czystą klasą abstrakcyjną, być może jedyną obserwowalną różnicą jest zachowanie słowa kluczowego "instanceof"? Zgadzam się, że interfejsy będą prawdopodobnie lepsze niż czysto abstrakcyjne klasy. Jednak w Angular 2 tylko te ostatnie mogą być używane jako tokeny dostawcy DI. –

+1

w istocie, dziękuję za wyłapanie instancji rzeczy, dodam ją do odpowiedzi na zakończenie (możesz dokonać edycji, jeśli chcesz). Jeśli chodzi o kątowy 2, myślę, że jest to problem specyficzny dla kątów2. :) – toskv

+0

@toskv, dziękuję za opis zastosowania słowa kluczowego "narzędzia" do interfejsów ORAZ klasy. Na przykład AngularJS 2.0 używa tego do implementacji swojej klasy "OnInit" (a nie "interfejsu"). Rozejrzałem się, czy masz odniesienie do tego. Nie widzę tego wyraźnie w dokumentacji TS. – MoMo

0

W przykładzie rozszerzeń, które podajesz, nie dodajesz niczego nowego do klasy. Tak więc jest on rozszerzony o nic. Mimo że rozszerzenie o nic nie jest poprawne, wydaje mi się, że w tym przypadku "narzędzia" byłyby bardziej odpowiednie. Ale pod koniec dnia są one równoważne.

2

Opierając się na @toskv's answer, jeśli rozszerzyć klasy abstrakcyjnej, trzeba zadzwonić super() w konstruktorze podklasy za. Jeśli używasz implementacji klasy abstrakcyjnej, nie musisz wywoływać super() (ale musisz wdrożyć wszystkie metody zadeklarowane w klasie abstrakcyjnej, w tym metody prywatne).

Implementacja klasy abstrakcyjnej zamiast jej rozszerzania może być przydatna, jeśli chcesz utworzyć próbną klasę do testowania bez obawy o zależności i konstruktor oryginalnej klasy.

0

Zostałem tutaj poprowadzony, ponieważ właśnie zadawałem sobie to samo pytanie i podczas czytania odpowiedzi przyszło mi do głowy, że wybór wpłynie również na operatora instanceof.

Ponieważ klasa abstrakcyjna jest wartością rzeczywistą, która jest emitowana do JS, może być używana do sprawdzania w czasie wykonywania, gdy podklasa ją rozszerza.

abstract class A {} 

class B extends A {} 

class C implements A {} 

console.log(new B() instanceof A) // true 
console.log(new C() instanceof A) // false 
Powiązane problemy