2012-05-08 40 views
8

Tôi đã đọc tài liệu của Dart và tôi hơi bối rối, có lẽ vì tôi đến từ Ruby, về cách sử dụng giao diện. Tất nhiên, giao diện không phải là duy nhất cho Dart và có khá nhiều giải thích trên đó khi người ta nên sử dụng một giao diện. Ví dụ: This one dường như nói rằng các giao diện chỉ hữu ích khi bạn ở trong một nhóm. Nó có nghĩa là gì ngay cả trong thế giới nguồn mở, nơi mọi người đọc và sử dụng lại mã của người khác?Khi nào sử dụng giao diện trong Dart?

Một cách giải thích thú vị tôi đã nhìn thấy dường như ngụ ý rằng giao diện được sử dụng:

  1. trong ngôn ngữ mà thiếu đa kế thừa, và
  2. cho rằng vấn đề họ bằng cách nào đó đóng vai trò như một cách giải quyết cho sự vắng mặt của đa thừa kế.

Tôi không hiểu điều đó. Tôi hiểu rằng các mô-đun trong Ruby là một giải pháp vì chúng cho phép tôi định nghĩa các phương thức thực sự với các thực thể. Giao diện chỉ cho phép tôi xác định những phương thức mà lớp triển khai thực hiện nó. Bắt là gì? Bất cứ ai có thể nói về một ví dụ hữu ích thực sự mà tôi có thể ngay lập tức thấy giá trị của việc sử dụng giao diện?

P.S. Trên một lưu ý liên quan, có cách nào để sử dụng nhiều thừa kế trong Dart?

Trả lời

19

Giao diện hữu ích vì chúng cho phép bạn chuyển đổi các triển khai của một lớp, trong khi vẫn cho phép xác thực rằng loại được truyền theo yêu cầu của giao diện.

Lấy sau (thường được sử dụng) ví dụ:

interface Quackable { 
    void quack(); 
} 

này quy định các yêu cầu của một lớp sẽ được chuyển đến một phương pháp như:

sayQuack(Quackable quackable) { 
    quackable.quack(); 
} 

cho phép bạn sử dụng bất kỳ cách triển khai nào của đối tượng có thể đặt được, chẳng hạn như:

class MockDuck implements Quackable { 
    void quack() => print("quack"); 
} 

class EnterpriseDuck implements Quackable { 
    void quack() { 
    // connect to three enterprise "ponds" 
    // and eat some server bread 
    // and say "quack" using an messaging system 
    } 

} 

Cả hai việc triển khai này sẽ hoạt động với hàm sayQuack(), nhưng một yêu cầu đòi hỏi cơ sở hạ tầng ít hơn đáng kể so với phương thức khác.

sayQuack(new EnterpriseDuck()); 
sayQuack(new MockDuck()); 

Tôi sử dụng mẫu này mọi lúc trong thế giới Java khi xây dựng các giải pháp sử dụng một số "doanh nghiệp vịt". Khi phát triển cục bộ, tất cả những gì tôi chỉ cần là có thể gọi hàm sayQuack() và trả về một số dữ liệu giả lập mã hóa cứng.

Duck gõ

Vì Dart là tùy chọn đánh máy, bạn không thực sự cần phải sử dụng giao diện, bạn chỉ cần viết một lớp có chứa các phương pháp chữ ký đúng sẽ làm việc (mặc dù các công cụ sẽ không thể để xác thực nó).

class Person { // note: no implements keyword 
    void quack() => "I'm not a duck"; 
} 

sayQuack(new Person()); // provides the quack method, so this will still work 

Tất cả các lớp là giao diện

Cuối cùng, tất cả các lớp học cũng là giao diện. Điều này có nghĩa rằng mặc dù hệ thống của bên thứ ba có thể đã được viết mà không cần sử dụng giao diện, nhưng bạn vẫn có thể sử dụng một lớp bê tông như thể nó là một giao diện.

Ví dụ, hãy tưởng tượng thư viện doanh nghiệp như sau:

class EnterpriseDuck { // note: no implements keyword 
    void quack() { 
    // snip 
    } 
} 

sayQuack(EnterpriseDuck duck) { // takes an instance of the EnterpriseDuck class 
    duck.quack(); 
} 

Và bạn muốn vượt qua một con vịt giả vào phương pháp sayQuack trong một cách mà các kiểm tra loại có thể xác nhận. Bạn có thể tạo mockDuck của bạn để thực hiện các giao diện ngụ ý bởi EnterpriseDuck, chỉ đơn giản bằng cách sử dụng các EnterpriseDuck như một giao diện:

class MockDuck implements EnterpriseDuck { 
    void quack() => "I'm a mock enterprise duck"; 
} 

Nhiều Inheritance

Xét về đa kế thừa, điều này là không thể trong Dart. Bạn có thể, tuy nhiên, thực hiện nhiều giao diện và cung cấp triển khai của riêng bạn trong những phương pháp cần thiết, ví dụ:

class MultiDuck implements Quackable, EnterpriseDuck, Swimable { 
    // snip... 
} 

Giao diện có thể có các lớp học mặc định

Khi bạn sử dụng Dart, bạn sẽ thấy rằng hầu hết các "lớp học "thực sự là giao diện. Danh sách, Chuỗi v.v ... ... là tất cả các giao diện có triển khai mặc định được cung cấp. Khi bạn gọi

List myList = new List(); 

bạn đang thực sự sử dụng giao diện Danh sách và từ khóa mới chuyển hướng từ giao diện sang triển khai Danh sách mặc định cơ bản.

Liên quan đến phát triển trong một đội

Giao diện này rất hữu ích trong việc phát triển đội ngũ, ngay cả trong thế giới mã nguồn mở. Giao diện xác định các phương thức và thuộc tính mà bạn nên xây dựng để thành phần của bạn hoạt động với thành phần của tôi. Bạn có thể xây dựng triển khai thử nghiệm của riêng mình cho giao diện đó và tôi có thể xây dựng triển khai thực hiện cụ thể của giao diện đó và khi chúng ta hoàn tất, chúng tôi có thể tích hợp. Nếu không có giao diện được chia sẻ, được công bố, tôi sẽ cần phải cung cấp triển khai cụ thể của tôi trước khi bạn thực sự có thể bắt đầu.

Hy vọng điều đó sẽ hữu ích!

+2

Cảm ơn rất nhiều Chris, đó chính xác là những gì tôi cần. Ngoài ra, tên lớp của bạn trong các ví dụ là đáng yêu. – snitko

+0

trong suy nghĩ của bạn, hai ý kiến ​​mã của bạn: '// note: no keyword keyword' thay vì '// note: no implement keyword'. – GameAlchemist

+3

Cân nhắc việc cập nhật điều này hoặc thêm nhận xét vào bài đăng này giải thích rằng từ khóa giao diện không còn được sử dụng trong Dart nữa. –

1

Giao diện là một phần của hệ thống kiểu trong Dart và nhập khai báo là tùy chọn. Điều này có nghĩa là các giao diện cũng là tùy chọn.

Giao diện giúp bạn ghi lại các phương pháp mà đối tượng của bạn phản hồi. Nếu bạn thực hiện giao diện thì bạn hứa sẽ thực hiện tất cả các phương thức trong giao diện.

Dart sử dụng thông tin này để trình bày cảnh báo thời gian biên dịch về các loại không phù hợp, để cung cấp thêm hữu ích gợi ý hỗ trợ mã và hỗ trợ một số phép tái cấu trúc.

+0

Chắc chắn, tôi hiểu chúng là tùy chọn. Và tôi không thấy giá trị khi sử dụng chúng. Biên dịch cảnh báo thời gian dường như không phải là một chiến thắng lớn. Tuy nhiên, tôi thừa nhận tôi có thể sai về cơ bản trong đánh giá của tôi. Đó là lý do tại sao tôi đang tìm kiếm một ví dụ thực tế minh họa giá trị của việc sử dụng Giao diện. – snitko

4

Về cơ bản, giao diện không có gì liên quan đến đa kế thừa. Có thể giả mạo nhiều giao diện thừa kế và lạm dụng khi thực hiện nó, nhưng nếu bạn muốn có nhiều thừa kế thực sự (hoặc mixin hoặc đặc điểm), thì Dart không cung cấp cho họ (hiện tại - tôi tin rằng mixins sẽ tìm đường vào một ngày nào đó).

Giao diện tốt nhất là hợp đồng rõ ràng.Giả sử bạn có hai thành phần AB cần phải làm việc với nhau. Bạn có thể gọi trực tiếp B từ A và nó sẽ hoạt động, nhưng lần sau bạn sẽ muốn thay đổi B, bạn sẽ phải xem A cách thức sử dụng nó. Đó là vì B không hiển thị giao diện rõ ràng. Có, từ phù hợp cho giao diện không phải là triển khai nhưng hiển thị.

Nếu bạn che giấu việc thực hiện B đằng sau một giao diện và chỉ cung cấp giao diện để A, sau đó bạn có thể thay đổi B theo ý thích và chỉ lo lắng về vẫn phơi bày cùng giao diện. Giao diện thậm chí có thể được tiếp xúc bởi nhiều hơn một lớp, và người gọi không phải quan tâm (hoặc thậm chí biết).

Lưu ý rằng giao diện từ có hai nghĩa ở đây: Tổng hợp đồng của các thành phần, mà cũng có thể được mô tả trong tiếng Anh đơn giản trong tài liệu, và một ngôn ngữ đặc biệt xây dựng giúp bạn mô tả (và cũng thi hành) một số phần của hợp đồng ngay bên trong ngôn ngữ lập trình.

Bạn không nhất thiết phải sử dụng cấu trúc ngôn ngữ, nhưng được coi là kiểu tốt để sử dụng nó để mô tả các phần của hợp đồng mà ngôn ngữ lập trình cho phép bạn.

Bây giờ, cái quái gì là hợp đồng ở đây? Nói một cách đơn giản, hợp đồng là mô tả của thành phần mong đợi từ người dùng của nó và những gì người dùng có thể mong đợi từ thành phần.

Ví dụ, giả sử tôi có một phương pháp mà tính giá trị tuyệt đối của một số:

class MathUtils { 
    /// Computes absolute value of given [number], which must be a [num]. 
    /// Return value is also a [num], which is never negative. 
    absoluteValue(number) { 
    ... here's the implementation ... 
    } 
} 

Hợp đồng ở đây là hoàn toàn được mô tả trong các bình luận tài liệu (tốt, không hoàn toàn, chúng tôi cũng có thể mô tả giá trị tuyệt đối là gì, nhưng điều này là đủ tốt). Vâng ... nhưng một số phần của bình luận có thể được thể hiện trực tiếp bằng ngôn ngữ, đúng không?

class MathUtils { 
    /// Computes absolute value of given [number]. 
    /// Return value is never negative. 
    num absoluteValue(num number) { 
    ... here's the implementation ... 
    } 
} 

Lưu ý rằng một số bộ phận của hợp đồng chỉ đơn giản là không thể được thể hiện bằng ngôn ngữ lập trình - đây, ngôn ngữ không có ý tưởng gì giá trị tuyệt đối là, điều này cần phải ở lại nhận xét. Ngoài ra, bạn không thể diễn tả rằng giá trị trả về không bao giờ là tiêu cực, vì vậy điều này cũng phải nằm trong nhận xét. Nhưng trên thực tế, độc giả của mã của bạn biết gì một giá trị tuyệt đối là (và nó không bao giờ là tiêu cực) và tên phương pháp là khá rõ ràng về mục đích, vì vậy những nhận xét có thể hoàn toàn bỏ qua:

class MathUtils { 
    num absoluteValue(num number) { 
    ... here's the implementation ... 
    } 
} 

Vì vậy, bây giờ, một số phần của hợp đồng được thể hiện một cách rõ ràng, sử dụng các phương tiện ngôn ngữ, và một số phần được thể hiện hoàn toàn (bạn dựa vào những người biết giá trị tuyệt đối là gì).

Và giao diện bằng ngôn ngữ được sử dụng để tách hợp đồng khỏi việc triển khai. Nó có lẽ là quá mức cần thiết để sử dụng trong các chương trình nhỏ, nhưng nó trả hết khi thực hiện các chương trình lớn hơn (mà không phải liên quan đến việc làm của nhóm).

Uff, điều này hóa ra dài hơn tôi mong đợi. Hy vọng rằng sẽ giúp.

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