2011-12-16 44 views
49

Tôi vẫn còn một số nhầm lẫn về điều này. Những gì tôi đã tìm thấy cho đến bây giờ làTại sao nên sử dụng Giao diện, Đa thừa kế và Giao diện, Lợi ích của Giao diện?

(câu hỏi tương tự đã được hỏi ở đây nhưng tôi đã có một số điểm khác.)

  1. Interface là tập hợp các phương pháp trừu tượng CHỈ và các lĩnh vực chính thức.

  2. Không có nhiều thừa kế trong Java.

  3. Giao diện có thể được sử dụng để đạt được nhiều kế thừa trong Java.

  4. Một điểm mạnh của thừa kế là chúng tôi có thể sử dụng mã của lớp cơ sở trong lớp dẫn xuất mà không cần viết lại. Có thể đây là điều quan trọng nhất để thừa kế ở đó.

Bây giờ ..

Q1. Vì các giao diện chỉ có các phương thức trừu tượng (không có mã) nên làm thế nào chúng ta có thể nói rằng nếu chúng ta đang thực hiện bất kỳ giao diện nào thì nó là thừa kế? Chúng tôi không sử dụng mã của nó.

Q2. Nếu thực hiện một giao diện không phải là thừa kế thì giao diện được sử dụng như thế nào để đạt được nhiều thừa kế?

Q3. Nhưng dù sao lợi ích của việc sử dụng Giao diện là gì? Họ không có bất kỳ mã nào. Chúng ta cần phải viết mã một lần nữa và một lần nữa trong tất cả các lớp chúng ta thực hiện nó.

Sau đó, tại sao tạo giao diện?

LƯU Ý: Tôi đã tìm thấy một trường hợp trong đó giao diện hữu ích. Một ví dụ của nó giống như trong giao diện Runnable chúng ta có phương thức public void run() trong đó chúng ta định nghĩa chức năng của thread và được xây dựng trong mã hóa rằng phương thức này sẽ được chạy như một luồng riêng biệt. Vì vậy, chúng tôi chỉ cần mã phải làm gì trong chuỗi, Phần còn lại được xác định trước. Nhưng điều này cũng có thể đạt được bằng cách sử dụng các lớp trừu tượng và tất cả.

Sau đó, lợi ích chính xác của việc sử dụng giao diện là gì? Nó thực sự là đa thừa kế mà chúng ta đạt được bằng cách sử dụng giao diện?

Trả lời

12

Giao diện là tập hợp các trường tĩnh cuối cùng và phương thức trừu tượng (Mới hỗ trợ Java 8 có phương thức tĩnh trong giao diện).

Giao diện được thực hiện trong các tình huống khi chúng tôi biết rằng một số công việc phải được thực hiện, nhưng cách thực hiện công việc có thể khác nhau. Nói cách khác, chúng ta có thể nói chúng ta thực hiện các giao diện để lớp của chúng ta bắt đầu hành xử theo một cách cụ thể.

Để tôi giải thích một ví dụ, chúng ta đều biết động vật là gì. Giống như Sư tử là một con vật, khỉ là một con vật, voi là một con vật, bò là một con vật và vân vân. Bây giờ chúng ta biết tất cả các loài động vật ăn một cái gì đó và ngủ. Nhưng cách mỗi con vật có thể ăn một cái gì đó hoặc ngủ có thể khác nhau. Giống như Sư tử ăn bằng cách săn bắt những con vật khác, nơi bò ăn cỏ. Nhưng cả hai đều ăn. Vì vậy, chúng ta có thể có một số mã giả như thế này,

interface Animal { 
    public void eat(); 
    public void sleep(); 
} 

class Lion implements Animal { 
    public void eat() { 
     // Lion's way to eat 
    } 

    public void sleep(){ 
     // Lion's way to sleep 
    } 
} 

class Monkey implements Animal { 
    public void eat() { 
     // Monkey's way to eat 
    } 

    public void sleep() { 
     // Monkey's way to sleep 
    } 
} 

Theo mã giả đề cập ở trên, bất cứ điều gì đó là có khả năng ăn uống hay ngủ sẽ được gọi là một con vật hoặc chúng tôi có thể nói đó là bắt buộc đối với tất cả các loài động vật ăn và ngủ nhưng cách ăn và ngủ phụ thuộc vào động vật.

Trong trường hợp giao diện, chúng tôi chỉ kế thừa hành vi, không phải mã thực tế như trong trường hợp thừa kế của lớp.

Q1. Vì các giao diện chỉ có các phương thức trừu tượng (không có mã) nên làm thế nào chúng ta có thể nói rằng nếu chúng ta đang thực hiện bất kỳ giao diện nào thì nó là thừa kế? Chúng tôi không sử dụng mã của nó.

Giao diện triển khai là loại thừa kế khác. Nó không giống với thừa kế của các lớp như trong lớp con thừa kế đó nhận mã thực để sử dụng lại từ lớp cơ sở.

Q2. Nếu thực hiện một giao diện không phải là thừa kế thì giao diện được sử dụng như thế nào để đạt được nhiều thừa kế?

Người ta nói rằng một lớp có thể triển khai nhiều giao diện. Nhưng chúng ta cần phải hiểu rằng thừa kế này khác với kế thừa của lớp.

Q3. Nhưng dù sao lợi ích của việc sử dụng Giao diện là gì? Họ không có bất kỳ mã nào. Chúng ta cần phải viết mã một lần nữa và một lần nữa trong tất cả các lớp chúng ta thực hiện nó.

Thực hiện giao diện đặt ép buộc vào lớp mà nó phải ghi đè lên tất cả các phương thức trừu tượng của nó.

Đọc thêm trong cuốn sách của tôi herehere

+2

Tôi cảm thấy cấu trúc mà bạn đã xây dựng trong mã của bạn sẽ tốt hơn và hợp lý hơn với việc thừa kế thừa kế hơn là với các giao diện thực hiện. Tôi nghĩ rằng đó là một ví dụ khá xấu –

+0

@gprathour Tôi đồng ý, vì vậy hãy cung cấp một ví dụ tốt hơn :) –

28

Q1. Vì các giao diện chỉ có các phương thức trừu tượng (không có mã) nên làm thế nào chúng ta có thể nói rằng nếu chúng ta đang thực hiện bất kỳ giao diện nào thì nó là thừa kế? Chúng tôi không sử dụng mã của nó.

Chúng tôi không thể. Giao diện không được sử dụng để đạt được nhiều thừa kế. Họ thay thế nó bằng an toàn hơn, mặc dù cấu trúc ít mạnh mẽ hơn. Lưu ý từ khóa implements thay vì extends.

Q2. Nếu thực hiện một giao diện không phải là thừa kế thì giao diện được sử dụng như thế nào để đạt được nhiều thừa kế?

Chúng không có. Với giao diện, một lớp đơn lẻ có thể có một số "lượt xem", các API hoặc khả năng khác nhau. Ví dụ. Một lớp học có thể là RunnableCallable cùng một lúc, trong khi cả hai phương pháp đều hoạt động tương tự.

Q3. Nhưng dù sao lợi ích của việc sử dụng Giao diện là gì? Họ không có bất kỳ mã nào. Chúng ta cần phải viết mã một lần nữa và một lần nữa trong tất cả các lớp chúng ta thực hiện nó.

Giao diện là loại đa thừa kế không có vấn đề mà sau này giới thiệu (như Diamond problem).

Có rất ít trường hợp sử dụng cho các giao diện:

  1. Object hiệu quả có hai sắc: a Tank cả VehicleWeapon. Bạn có thể sử dụng một thể hiện của Tank trong đó trường hợp cũ hoặc sau được mong đợi (đa hình). Điều này hiếm khi là một trường hợp trong đời thực và thực sự là một ví dụ hợp lệ trong đó nhiều thừa kế sẽ tốt hơn (hoặc các đặc điểm).

  2. trách nhiệm đơn giản: một thể hiện của đối tượng Tank trong một trò chơi cũng là Runnable để cho bạn thực hiện nó trong một chủ đề và một ActionListener để đáp ứng với các sự kiện chuột.

  3. Giao diện gọi lại: nếu đối tượng thực hiện giao diện gọi lại, nó sẽ được thông báo về vòng đời hoặc các sự kiện khác.

  4. Giao diện điểm đánh dấu: không thêm bất kỳ phương pháp nào, nhưng có thể truy cập dễ dàng qua instanceof để khám phá khả năng hoặc mong muốn của đối tượng. SerializableCloneable là ví dụ về điều này.

Điều bạn đang tìm kiếm là đặc điểm (như trong Scala), rất tiếc là không có trong Java.

+0

Bạn có thể vui lòng xây dựng các lợi ích của việc sử dụng giao diện không? – gprathour

+0

@GPSingh: Tôi đã cố thêm vài điểm bên dưới 'Q3'. Bạn có thêm một số câu hỏi không? –

3

Thừa kế là khi một lớp xuất phát từ một lớp khác (có thể trừu tượng) hoặc Giao diện. Điểm mạnh nhất của đối tượng được định hướng (thừa kế) là không tái sử dụng mã (có nhiều cách để làm điều đó), nhưng đa hình.

Đa hình là khi bạn có mã sử dụng giao diện, đối tượng thể hiện của nó có thể thuộc bất kỳ lớp nào có nguồn gốc từ giao diện đó. Ví dụ tôi có thể có một phương thức như vậy: public void Pet (động vật IAnimal) và phương thức này sẽ nhận được một đối tượng là một thể hiện của Dog hoặc Cat kế thừa từ IAnimal. hoặc tôi có thể có mã như vậy: Động vật IAnimal và sau đó tôi có thể gọi một phương thức của giao diện này: animal.Eat() mà Chó hoặc Mèo có thể thực hiện theo cách khác.

Ưu điểm chính của giao diện là bạn có thể kế thừa từ một số trong số chúng, nhưng nếu bạn cần kế thừa từ chỉ một bạn có thể sử dụng lớp trừu tượng.Đây là một bài viết giải thích thêm về sự khác nhau giữa một lớp trừu tượng và một giao diện: http://www.codeproject.com/KB/cs/abstractsvsinterfaces.aspx

4
  1. Từ "thừa kế" vẫn thường được sử dụng khi một lớp thực hiện một giao diện, mặc dù "Giao diện thực hiện" (như trái ngược với "Inheritance Concrete") sẽ là IMO thích hợp hơn. Đồng bằng "Thừa kế" nên được dành riêng cho thừa kế bê tông (kéo dài).

  2. Bạn có thể nhận được 'hiệu ứng' của đa thừa kế bằng cách triển khai nhiều giao diện trên một lớp và sau đó triển khai tất cả các phương thức, thuộc tính và sự kiện cần thiết của tất cả các giao diện. Một kỹ thuật phổ biến để thực hiện điều này với các lớp cụ thể là bằng cách thực hiện các mối quan hệ 'has-a' (composition) với các lớp thực hiện các giao diện bên ngoài bằng cách 'kết nối' việc triển khai thực hiện cho từng triển khai lớp bên trong. Các ngôn ngữ như C++ hỗ trợ nhiều kế thừa cụ thể trực tiếp.

  3. Giao diện cho phép các lớp hiện có (ví dụ: khung công tác) tương tác với các lớp mới của bạn mà không bao giờ 'thấy' chúng trước đây, vì khả năng giao tiếp với một giao diện đã biết. Hãy nghĩ về một giao diện như một hợp đồng. Bằng cách thực hiện giao diện này trên một lớp, bạn bị ràng buộc theo hợp đồng để đáp ứng các nghĩa vụ bắt buộc của nó.

Ví dụ 'thực tế' sẽ là ổ cắm tường điện - nó cung cấp một giao diện chung (đường dây, trung tính và trái đất) và công tắc bật/tắt, và có một số quy ước 'hiểu' như điện áp , tần số và dòng điện tối đa. Nhưng bạn có thể cắm quạt, ấm đun nước, hoặc một số thiết bị mới được phát minh vào năm sau, mặc dù thiết bị này không tồn tại khi giao diện được thiết kế.

Giao diện tuyệt vời để ghép nối lỏng lẻo các lớp (Xem Dependency Inversion Principle and Interface Segregation Principles of SOLID) và được sử dụng rộng rãi cho mục đích Kiểm tra đơn vị và Phụ thuộc.

9

KISS

Tôi đã tìm kiếm trong nhiều ngày, nhiều tuần nay cố gắng tìm hiểu giao diện và dường như đọc cùng sự giúp đỡ chung; Tôi không cố gắng để disparage những đóng góp, nhưng tôi nghĩ rằng bóng đèn chỉ cần nhấp vì vậy tôi chuffed :))

Tôi thích giữ nó đơn giản ngu ngốc, do đó sẽ proffer mới được tìm thấy giao diện của tôi.

Tôi là người lập trình bình thường nhưng tôi muốn đăng mã này tôi đã viết bằng VB.NET (nguyên tắc giống nhau cho các ngôn ngữ khác), để giúp người khác hiểu giao diện.

Nếu tôi nhầm, vui lòng cho người khác biết trong phần tiếp theo nhận xét.

Giải thích

Ba nút trên một hình thức, cách nhấn mỗi người tiết kiệm một tham chiếu lớp khác nhau để biến giao diện (_data). Toàn bộ các điểm tham chiếu lớp khác nhau vào một biến giao diện, là những gì tôi không hiểu vì nó có vẻ thừa, sau đó sức mạnh của nó trở nên hiển nhiên với msgbox, tôi chỉ cần gọi phương thức SAME để thực hiện tác vụ tôi cần, trong này case 'GetData()', sử dụng phương thức trong lớp hiện đang được tổ chức bởi biến tham chiếu giao diện (_data).

Vì vậy, tuy nhiên tôi muốn lấy dữ liệu của mình (từ cơ sở dữ liệu, web hoặc tệp văn bản), nó chỉ được thực hiện bằng cách sử dụng tên phương thức tương tự ; mã đằng sau việc triển khai đó ... tôi không quan tâm.

Sau đó, dễ dàng thay đổi từng mã lớp bằng giao diện mà không có bất kỳ sự phụ thuộc nào ... đây là mục tiêu chính trong OO và đóng gói.

Khi sử dụng

lớp Mã và nếu bạn nhận thấy cùng một động từ dùng cho các phương pháp, như 'GetData()', thì đó là một ứng cử viên tốt để thực hiện một giao diện trên lớp và sử dụng tên phương pháp như một trừu tượng/giao diện.

Tôi chân thành hy vọng điều này sẽ giúp một người bạn noob với nguyên tắc khó khăn này.

Public Class Form1 

Private _data As IData = Nothing 

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
    _data = New DataText() 
    MsgBox(_data.GetData()) 
End Sub 

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 
    _data = New DataDB() 
    MsgBox(_data.GetData()) 
End Sub 

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click 
    _data = New DataWeb() 
    MsgBox(_data.GetData()) 
End Sub 

End Class 

Public Interface IData 
Function GetData() As String 
End Interface 

Friend Class DataText : Implements IData 

Friend Function GetData() As String Implements IData.GetData 
    Return "DataText" 
End Function 

End Class 

Friend Class DataDB : Implements IData 

Friend Function GetData() As String Implements IData.GetData 
    Return "DataDB" 
End Function 

End Class 

Friend Class DataWeb : Implements IData 

Friend Function GetData() As String Implements IData.GetData 
    Return "DataWeb" 
End Function 

End Class 
+0

thực sự rất tốt. +1 –

0

Giao diện được thực hiện sao cho lớp học bắt đầu hoạt động theo một cách cụ thể. Đó là tôi sẽ nói.

4

Đây là câu hỏi rất cũ và bản phát hành java-8 đã thêm nhiều tính năng hơn & nguồn vào giao diện.

Một tuyên bố giao diện có thể chứa

  1. phương pháp chữ ký
  2. phương pháp mặc định
  3. phương pháp tĩnh
  4. định nghĩa không đổi.

Các phương pháp duy nhất mà có việc thực hiện trong giao diện là mặc địnhtĩnh phương pháp.

Sử dụng giao diện:

  1. Để xác định một hợp đồng
  2. Để liên kết các lớp học không liên quan với có khả năng (ví dụ như các lớp học thực hiện giao diện Serializable có thể hoặc có thể không có bất kỳ mối quan hệ giữa trừ khi triển khai giao diện đó
  3. Để cung cấp hoán đổi cho nhau implem entation ví dụ: Strategy_pattern
  4. mặc định phương pháp cho phép bạn thêm chức năng mới cho giao diện của thư viện của bạn và đảm bảo nhị phân tương thích với mã được viết cho phiên bản cũ của những giao diện
  5. Tổ chức phương pháp helper trong thư viện của bạn với phương pháp tĩnh (bạn có thể giữ các phương pháp tĩnh cụ thể cho một giao diện trong cùng một giao diện chứ không phải trong một lớp riêng biệt)

Hãy xem câu hỏi SE liên quan này để biết ví dụ về mã để hiểu các khái niệm tốt hơn:

How should I have explained the difference between an Interface and an Abstract class?

Trở lại với câu hỏi của bạn:

Q1. Vì các giao diện chỉ có các phương thức trừu tượng (không có mã) nên làm thế nào chúng ta có thể nói rằng nếu chúng ta đang thực hiện bất kỳ giao diện nào thì nó là thừa kế? Chúng tôi không sử dụng mã của nó.

Q2. Nếu thực hiện một giao diện không phải là thừa kế thì giao diện được sử dụng như thế nào để đạt được nhiều thừa kế?

Giao diện có thể chứa mã cho tĩnhmặc định phương pháp. Các phương pháp mặc định này cung cấp khả năng tương thích ngược & các phương pháp tĩnh cung cấp chức năng trợ giúp /tiện ích.

Bạn không thể có nhiều quyền thừa kế trong java và giao diện không phải là cách để có được nó. Giao diện chỉ có thể chứa hằng số. Vì vậy, bạn không thể kế thừa trạng thái nhưng bạn có thể thực hiện hành vi.

Bạn có thể thay thế thừa kế với khả năng . Giao diện cung cấp nhiều khả năng để triển khai các lớp học.

Q3. Nhưng dù sao lợi ích của việc sử dụng Giao diện là gì? Họ không có bất kỳ mã nào. Chúng ta cần phải viết mã một lần nữa và một lần nữa trong tất cả các lớp chúng ta thực hiện nó.

Tham khảo phần "sử dụng giao diện" trong câu trả lời của tôi.

-1

Giao diện

Giao diện là hợp đồng xác định cách tương tác với đối tượng. Chúng hữu ích để thể hiện cách thức nội bộ của bạn có ý định tương tác với một đối tượng. Theo sau Inversion phụ thuộc API công khai của bạn sẽ có tất cả các tham số được thể hiện bằng giao diện. Bạn không quan tâm làm thế nào nó làm những gì bạn cần nó để làm, chỉ cần nó làm chính xác những gì bạn cần nó để làm.

Ví dụ: Bạn có thể chỉ cần Vehicle để vận chuyển hàng hóa, bạn không quan tâm đến phương thức vận chuyển cụ thể.

Thừa kế

Thừa kế là phần mở rộng của một triển khai cụ thể. Việc triển khai đó có thể hoặc không thể đáp ứng một giao diện cụ thể. Bạn nên mong đợi một tổ tiên của một triển khai cụ thể chỉ khi bạn quan tâm về cách thức.

Ví dụ: Bạn có thể cần Plane triển khai phương tiện để vận chuyển nhanh.

Thành phần

Thành phần có thể được sử dụng thay thế cho kế thừa. Thay vì lớp của bạn mở rộng một lớp cơ sở, nó được tạo ra với các đối tượng thực hiện các phần nhỏ hơn của trách nhiệm của lớp chính. Thành phần được sử dụng trong facade patterndecorator pattern.

Ví dụ: Bạn có thể tạo ra một lớp DuckBoat (DUKW) mà thực hiện LandVehicleWaterVehicle mà cả hai thực hiện Vehicle gồm TruckBoat triển khai.

câu trả lời

Q1.Vì các giao diện chỉ có các phương thức trừu tượng (không có mã) nên làm thế nào chúng ta có thể nói rằng nếu chúng ta đang thực hiện bất kỳ giao diện nào thì nó là thừa kế? Chúng tôi không sử dụng mã của nó.

Giao diện không được kế thừa.

Q2. Nếu thực hiện một giao diện không phải là thừa kế thì giao diện được sử dụng như thế nào để đạt được nhiều thừa kế?

Giao diện không đạt được nhiều thừa kế. Họ thể hiện rằng một lớp học có thể phù hợp với nhiều vai trò.

Q3. Nhưng dù sao lợi ích của việc sử dụng Giao diện là gì? Họ không có bất kỳ mã nào. Chúng ta cần phải viết mã một lần nữa và một lần nữa trong tất cả các lớp chúng ta thực hiện nó.

Một trong những lợi ích chính của giao diện là cung cấp tách mối quan tâm:

  • Bạn có thể viết một lớp học mà làm điều gì đó với lớp khác mà không cần chăm sóc như thế nào lớp đó được thực hiện.
  • Bất kỳ sự phát triển nào trong tương lai đều có thể tương thích với việc triển khai của bạn mà không cần mở rộng một lớp cơ sở cụ thể.

Theo tinh thần DRY bạn có thể viết triển khai thỏa mãn giao diện và thay đổi trong khi vẫn tôn trọng open/closed principal nếu bạn tận dụng sáng tác.

+0

IRT các downvotes, làm thế nào tôi có thể cải thiện câu trả lời này? –

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