2013-01-15 39 views
70

Trong TypeScript, khi tạo tệp khai báo nguồn .d.ts, cái nào là thích hợp hơn và tại sao?Sự khác nhau giữa "lớp khai báo" và "giao diện" trong TypeScript

declare class Example { 
    public Method(): void; 
} 

hoặc

interface Example { 
    Method(): void; 
} 

Sự khác biệt mà tôi có thể nói là rằng giao diện không thể có phương pháp tĩnh, vì vậy bạn phải sử dụng một lớp cho điều đó. Cả hai không sản xuất bất kỳ đầu ra JS, vì vậy có lẽ nó không quan trọng?

+0

Xem http://stackoverflow.com/a/14323673/1704166 –

+0

Tôi không cảm thấy rằng một trong hai mô tả này thực sự giúp bạn mô tả bạn sẽ sử dụng cái khác vì cả hai đều có thể thực hiện điều tương tự mà không có đầu ra JS. – Chris

Trả lời

118

interface là khi bạn chỉ muốn mô tả hình dạng của một đối tượng. Không có thế hệ mã, bao giờ hết, đối với các giao diện - chúng chỉ là một tạo phẩm trong hệ thống kiểu. Bạn sẽ thấy không có sự khác biệt trong việc tạo mã cho một lớp tùy thuộc vào việc nó có mệnh đề là implements hay không.

declare class là khi bạn muốn mô tả một hiện lớp (thường là một lớp nguyên cảo, nhưng không phải luôn luôn) có nghĩa là sẽ được bên ngoài hiện tại (ví dụ, bạn có hai .ts file biên dịch để hai .js các tệp và cả hai được bao gồm qua các thẻ script trong một trang web). Nếu bạn kế thừa từ một số class sử dụng extends (bất kể loại cơ sở là declare class hoặc class thường xuyên) thì trình biên dịch sẽ tạo tất cả mã để móc chuỗi nguyên mẫu và trình tạo chuyển tiếp và những gì không.

Nếu bạn cố gắng kế thừa từ một số declare class mà lẽ ra phải là một giao diện, bạn sẽ gặp lỗi thời gian chạy vì mã được tạo ra đó sẽ đề cập đến một đối tượng không có biểu hiện thời gian chạy.

Ngược lại, nếu bạn chỉ đơn giản là implement một giao diện phải là declare class, bạn sẽ phải tự mình thực hiện lại tất cả các thành viên và sẽ không tận dụng bất kỳ mã nào sử dụng lại từ là lớp cơ sở và các hàm kiểm tra chuỗi nguyên mẫu khi chạy sẽ từ chối đối tượng của bạn vì không thực sự là một thể hiện của lớp cơ sở.

Để có được thực sự Nerdy, nếu bạn có một ++ nền C, bạn gần như có thể nghĩ về interface như typedefdeclare class như một lời tuyên bố extern của một nhà xây dựng mà thiếu chặt chẽ một định nghĩa trong đơn vị biên dịch này.

Từ một mặt tiêu thụ thuần túy (viết mã bắt buộc, không thêm loại mới), khác biệt duy nhất giữa interfacedeclare class là bạn không thể new giao diện. Tuy nhiên, nếu bạn dự định extend/implement một trong các loại này trong một số class mới, bạn hoàn toàn phải chọn chính xác giữa interfacedeclare class. Chỉ một trong số họ sẽ làm việc.

Hai quy tắc đó sẽ phục vụ bạn tốt:

  • là tên của loại xếp thẳng với một hàm constructor (một cái gì đó invokable với new) đó là thực hiện trong thời gian chạy (ví dụ Date, nhưng JQueryStatic không phải là) ? Nếu no, bạn chắc chắn muốn interface
  • Tôi có đang xử lý một lớp được biên dịch từ một tệp TypeScript khác hoặc một thứ tương tự đủ không? Nếu , sử dụng declare class
+0

Bạn có thể tạo một giao diện mới trong bản mẫu. Giới hạn duy nhất là thừa kế. –

+2

Bạn không thể gọi toán tử 'new' trên một kiểu giao diện. Tuy nhiên, các giao diện có thể có các chữ ký xây dựng, có nghĩa là bạn có thể gọi toán tử 'new' trên một giá trị của kiểu giao diện. Điều này rất khác so với cách 'lớp' hoạt động, trong đó chữ ký xây dựng nằm trên tên kiểu chính nó chứ không phải trên một biểu thức của kiểu đó. –

+0

Nếu bạn đi tuyến đường thêm một hàm tạo vào một giao diện, nó phải là thành viên CHỈ của giao diện, ngoại trừ 'số liệu thống kê' của lớp. Không kết hợp giao diện của hàm xây dựng với giao diện của đối tượng được xây dựng. Nếu bạn làm như vậy, hệ thống kiểu cho phép silliness như: new (new x()), trong đó x: Interface. –

12

Bạn có thể thực hiện các giao diện:

class MyClass implements Example { 
    Method() { 

    } 
} 

Trong khi cú pháp declare class thực sự dự định sẽ được sử dụng để thêm định nghĩa kiểu cho mã bên ngoài mà không được viết bằng nguyên cảo - vì vậy việc thực hiện là "nơi khác".

+0

Vì vậy, bạn đang cho rằng lớp khai báo nên được sử dụng để mô tả mã không được viết bằng TypeScript? Tôi sẽ giả định rằng trường hợp, nhưng trong tập tin jquery.d.ts đã đăng ký, JQueryStatic là một giao diện được thực hiện bởi: khai báo var $: JQueryStatic Tôi có thể là khai báo lớp $ { tĩnh công cộng .. } – Chris

+0

Lý do duy nhất tôi có thể nghĩ về điều này là nếu bạn không muốn mọi người mở rộng lớp học - sử dụng giao diện nghĩa là bạn sẽ phải cung cấp toàn bộ quá trình triển khai. – Fenton

+0

Làm cho tinh thần. Có lẽ đó là lý do. – Chris

3

Trong điều khoản của layman, declare được sử dụng trong .ts/d.ts tập tin để nói với trình biên dịch rằng chúng ta nên mong đợi từ khóa chúng tôi declaring để tồn tại trong môi trường đó, ngay cả khi nó không phải là được xác định trong tệp hiện tại. Điều này sau đó sẽ cho phép chúng ta có an toàn kiểu khi sử dụng đối tượng đã khai báo, vì trình biên dịch Typescript bây giờ biết rằng một số thành phần khác có thể cung cấp biến đó.

Các vấn đề liên quan