2016-03-14 29 views
27

Giả sử tôi có một lớp trừu tượng thuần túy (tức là một lớp trừu tượng mà không cần bất kỳ thực hiện):Mở rộng so với thực hiện một lớp trừu tượng thuần túy trong nguyên cảo

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

Giống như trong C# và Java, tôi có thể mở rộng lớp trừu tượng:

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

Nhưng không giống như trong C# và Java, tôi cũng có thể thực hiện lớp trừu tượng:

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

Lớp học BC hoạt động khác nhau như thế nào? Tại sao tôi chọn cái này so với cái kia?

(Hiện nay, nguyên cảo handbooklanguage specification không bao gồm lớp trừu tượng.)

+0

Hiện có một phần về Lớp trừu tượng trong sổ tay TypeScript. https://www.typescriptlang.org/docs/handbook/classes.html Cảm ơn câu hỏi này! Tôi không có ý tưởng 'trừu tượng' đã có sẵn trong TS và điều này đã giúp tôi hiểu nó. – theUtherSide

Trả lời

33

Các thực hiện từ khóa đối xử với A lớp như một giao diện, có nghĩa là C có để thực hiện tất cả các phương pháp quy định tại Một, bất kể họ có triển khai hay không trong A. Ngoài ra không có cuộc gọi đến các phương thức siêu trong C.

mở rộng hoạt động giống như những gì bạn mong đợi từ từ khóa. Bạn phải thực hiện chỉ các phương thức trừu tượng và các cuộc gọi siêu có sẵn/được tạo.

Tôi đoán rằng trong trường hợp các phương pháp trừu tượng, nó không tạo nên sự khác biệt. Nhưng bạn hiếm khi có một lớp chỉ với các phương pháp trừu tượng, nếu bạn làm như vậy sẽ tốt hơn nhiều nếu chỉ chuyển đổi nó thành giao diện .

Bạn có thể dễ dàng thấy điều này bằng cách xem mã được tạo. Tôi đã làm một ví dụ sân chơi here.

+3

Nếu 'A' là một lớp trừu tượng thuần túy, có lẽ sự khác biệt quan sát duy nhất là hành vi của từ khóa' instanceof'? Tôi đồng ý rằng các giao diện có lẽ sẽ thích hợp hơn với các lớp trừu tượng thuần túy. Tuy nhiên, trong Angular 2, chỉ cái thứ hai mới có thể được sử dụng như các thẻ nhà cung cấp DI. –

+1

thực sự, cảm ơn vì đã phát hiện ra điều gì đó, tôi sẽ thêm nó vào câu trả lời để hoàn thành (bạn có thể chỉnh sửa nếu muốn). Đối với angular2, tôi đoán đó là một vấn đề cụ thể của angular2. :) – toskv

+0

@toskv, cảm ơn bạn đã mô tả tính khả dụng của từ khóa 'thực hiện' đối với giao diện AND class. Ví dụ, AngularJS 2.0 sử dụng điều này để thực hiện 'OnInit' CLASS (chứ không phải là 'giao diện'). Tôi đã nhìn xung quanh, bạn có một tham chiếu đến điều này. Tôi không thấy rõ trong tài liệu TS. – MoMo

0

Trong ví dụ mở rộng mà bạn cung cấp cho bạn, không thực sự thêm bất kỳ điều gì mới vào lớp học. Vì vậy, nó được mở rộng bởi không có gì. Mặc dù mở rộng bởi không có gì là hợp lệ Typecript nó dường như với tôi rằng trong trường hợp này 'thực hiện' sẽ là thích hợp hơn. Nhưng vào cuối ngày chúng tương đương nhau.

2

Xây dựng trên @toskv's answer, nếu bạn mở rộng lớp trừu tượng, bạn phải gọi super() trong hàm tạo của lớp con. Nếu bạn triển khai lớp trừu tượng, bạn không phải gọi super() (nhưng bạn phải triển khai tất cả các phương thức được khai báo trong lớp trừu tượng, bao gồm cả phương thức riêng).

Thực hiện một lớp trừu tượng thay vì mở rộng nó có thể hữu ích nếu bạn muốn tạo một lớp mô hình để thử nghiệm mà không phải lo lắng về các phụ thuộc của lớp ban đầu và hàm tạo.

0

Tôi đã được dẫn đầu ở đây vì tôi vừa mới tự hỏi chính mình cùng một câu hỏi và đọc câu trả lời nó cho tôi biết rằng lựa chọn cũng sẽ ảnh hưởng đến nhà điều hành instanceof.

Vì một lớp trừu tượng là một giá trị thực tế được phát ra cho JS, nó có thể được sử dụng để kiểm tra thời gian chạy khi một lớp con mở rộng nó.

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 
Các vấn đề liên quan