2011-12-07 26 views
12

nếu chúng ta đưa một đối tượng vào giao diện, đối tượng này sẽ không thể gọi các phương thức riêng của nó không? trong ví dụ sau, myObj sẽ chỉ có thể gọi các phương thức MyInterface?đưa đối tượng vào giao diện trong java?

MyInterface myObj = new Obj(); 

Nếu điều này là đúng, sự khác biệt giữa những 2 đối tượng là những gì:

MyInterface myObj = new Obj(); 

MyInterface mySec = new Sec(); 

Nhờ sự giúp đỡ của bạn

+0

[this] (http://docs.oracle.com/javase/tutorial/java/concepts/interface.html) có thể hữu ích. – Nerdtron

Trả lời

16
MyInterface myObj = new Obj(); 
MyInterface mySec = new Sec(); 

Đối với điều này là hợp pháp, cả hai ObjSec sẽ phải là người triển khai của MyInterface. Sự khác biệt giữa hai đối tượng này sẽ là cách chúng cung cấp triển khai đó. ObjSec có thể làm hai điều rất khác nhau hoặc rất giống nhau, nhưng tính phổ biến của chúng là chúng sẽ tuân thủ một hợp đồng mà bạn có thể dựa vào. Hãy xem xét bạn có một phương pháp

public void doSomethingWith(MyInterface thing) { 
    thing.frob(); 
} 

Mỗi đối tượng, myObjmySec, có thể được thông qua vào phương pháp này, và phương pháp này sau đó có thể sử dụng phương pháp frob của đối tượng đó (giả sử frob là một phần của việc kê khai giao diện). Đây là giải phóng. Điều này cho phép bạn làm những điều rất mạnh mẽ, bằng cách lập trình cho các giao diện và không triển khai. Ví dụ, bạn có thể mở rộng chức năng của các lớp và không thay đổi một dòng mã trong các lớp đó, bạn chỉ cần thực hiện một sự phụ thuộc khác nhau. Bạn không bị ràng buộc với, hoặc được kết hợp với, bất kỳ ý nghĩa nào bên trong phương thức doSomethingWith.

nhưng tôi cũng đọc rằng nếu chúng ta khai báo myObj đối tượng như MyInterface, myObj sẽ không thể sử dụng phương pháp riêng của mình (từ lớp obj), là rằng sửa

nội , các trường hợp của Obj sẽ tiếp tục có toàn quyền truy cập vào API Obj. myObj vẫn là Obj, nó sẽ luôn có thể sử dụng chi tiết triển khai của riêng nó.

public interface MyInterface { 
    void frob(); 
} 

public class Obj implements MyInterface { 

    public void frob() { 
     doFrobbing(); 
    } 

    private void doFrobbing() { 
     System.out.println("frobbing"); 
    } 

    public static void main(String[] args) { 
     MyInterface myObj = new Obj(); 
     myObj.frob(); // still internally calls doFrobbing() 
     ((Obj)myObj).doFrobbing(); // visible only via class reference 
    } 
} 

Instances của Obj vẫn sẽ là trường hợp của Obj, và những trường hợp vẫn có thể sử dụng doFrobbing. Bên ngoài, những người sử dụng những trường hợp đó thông qua tham chiếu giao diện sẽ chỉ có thể truy cập các phương thức giao diện.

+0

cảm ơn anthony cho lời giải thích tuyệt vời này, tôi hiểu điều này, và thậm chí nhiều hơn bây giờ cảm ơn, nhưng tôi cũng đọc rằng nếu chúng ta khai báo đối tượng 'myObj' như MyInterface,' myObj' sẽ không thể sử dụng các phương thức riêng của nó (từ class 'Obj'), có đúng không? – Paul

+0

@Paul, câu hỏi hay, câu trả lời được cập nhật. –

+0

cảm ơn bạn đã cập nhật, vì vậy, điểm cần làm là gì? (ẩn các phương thức 'Obj' khi' MyInterface' là kiểu) Một giao diện "tồn tại" để "thêm" một số phương thức vào một đối tượng, phải không ?, vậy tại sao nó ẩn các phương thức khác? (hoặc có thể không có lý do cho điều đó, điều này làm việc bởi vì, như là một quy tắc chung trong mọi ngôn ngữ lập trình, một "loại" hoạt động như thế?) – Paul

1

Chỉ các phương thức trong giao diện là có thể nhìn thấy, nhưng tất cả các phương pháp trong đối tượng vẫn có thể được gọi, miễn là chúng có thể truy cập được nếu không. Ví dụ:

public interface MyInterface { 
    String getName(); 
} 

public class Obj implements MyInterface { 
    private String getFirstName() { 
     return "John"; 
    } 

    private String getLastName() { 
     return "Doe"; 
    } 

    @Override 
    public String getName() { 
     return getFirstName() + " " + getLastName(); 
    } 
} 

public class Sec implements MyInterface { 
    private String getDate() { 
     return new Date().toString(); 
    } 

    @Override 
    public String getName() { 
     return getDate(); 
    } 
} 

Trong các trường hợp trên, cả hai ObjSec có thể gọi các thành viên tư nhân của họ, mặc dù họ sẽ không được hiển thị trong các lớp khác. Vì vậy, khi bạn nói ...

MyInterface myObj = new Obj(); 
MyInterface mySec = new Sec(); 

...như bạn đã hỏi trong câu hỏi, trong khi đúng là trong myObjmySec thì phương pháp duy nhất có thể nhìn thấy là getName(), việc triển khai cơ bản của chúng có thể khác nhau.

+0

Cảm ơn jonathan vì lời giải thích tuyệt vời này, mmh, ok tôi hiểu nó nhiều hơn một chút, vì vậy nếu các phương thức 'Obj' không được hiển thị bởi các lớp khác, trong trường hợp nào nó quan trọng? (bạn có một ví dụ đơn giản?) – Paul

+0

Xin lỗi, tôi không chắc chắn tôi hiểu câu hỏi của bạn. –

1

Không có sự khác biệt. Bạn sẽ chỉ có thể gọi các phương thức giao diện MyInterface trên myObjmySec. Rõ ràng mã của bạn sẽ chỉ biên dịch nếu cả hai ObjSec triển khai giao diện Myinterface.

+0

Cảm ơn câu trả lời nhanh của bạn, vì vậy đây là điều: nếu chúng ta bắt đầu dự án mà không có giao diện, và sau đó chúng ta muốn thực hiện một giao diện vì chúng ta cần thêm các phương thức để thêm vào các lớp 'A' và' B': các phương thức trước đó từ 'A' và' B' vì chúng ta sẽ khai báo 'a' và' b' làm đối tượng của tôi ... – Paul

+0

@Paul Giao diện tồn tại với mục đích thêm một số giao diện * phổ biến (hoặc nói cách khác là một hợp đồng) cho các lớp khác nhau và cho phép các lớp đó thực sự triển khai chức năng * theo hợp đồng. Bạn không thực sự cần thiết để sử dụng các giao diện nếu bạn muốn thêm các phương thức mới vào một lớp. Dưới đây là định nghĩa đơn giản về giao diện là: http://docs.oracle.com/javase/tutorial/java/concepts/interface.html – Strelok

+0

cảm ơn Strelok, sự hiểu lầm của tôi là thay đổi "Loại" của một đối tượng và đặt giao diện là "Loại", điều này có nghĩa là các phương thức của obj không còn "hiển thị" nữa ... điều này làm tôi bối rối một chút. Mặc dù vậy, tôi đã có nguyên tắc giao diện, tôi hiểu rằng các giao diện là một số phương thức mà 2 lớp sẽ chia sẻ, nhưng những gì tôi không chắc là: nếu "Giao diện" là kiểu, các phương thức khác từ lớp myObj đã thắng Không thể nhìn thấy nữa – Paul

0

Trong mã bạn đã cho thấy bạn không bao giờ thực hiện bất kỳ phôi nào.

Việc sử dụng giao diện điển hình là xác định một số phương pháp sẽ có sẵn mà không cần quan tâm đến việc triển khai cụ thể.

Một ví dụ điển hình về điều này là những người nghe trong JDK chuẩn. Ví dụ: PropertyChangeListener. Đây là một giao diện định nghĩa một phương thức có thể được gọi khi 'một thuộc tính được thay đổi'. Một cách sử dụng điển hình của giao diện này là đính kèm nó vào một lớp có thuộc tính và lớp này sẽ cảnh báo những người nghe đó khi một trong các thuộc tính của nó đã thay đổi.

Lớp học không quan tâm những gì người nghe sẽ làm. Nó chỉ dựa trên thực tế phương pháp propertyChange này sẽ hiện diện và gọi phương thức đó.

Lớp chỉ có thể gọi phương thức này trên trình nghe vì nó chỉ biết về phương thức được xác định trong giao diện. Nếu những thính giả đó có các phương pháp khác, họ có thể tự gọi những phương pháp đó, nhưng đó chỉ là vì họ biết họ có nhiều giao diện hơn.

0
MyInterface mi = new Obj(); 
mi.getInterfaceMethods(); (methods in the MyInterface) 

if(mi instanceof Obj) { 
    mi.getObjMethods(); (methods in the Obj) 
} 
0

Thay đổi loại biến (tức là tham chiếu) không thay đổi chính đối tượng đó. Một đối tượng luôn có thể gọi các phương thức riêng của nó, bất kể các biến khai báo là tham chiếu đến nó.

1
MyInterface myObj = new Obj(); 
MyInterface mySec = new Sec(); 

Bạn khai báo một thể hiện của MyInterface có tên myObj. Bạn khởi tạo nó bằng Obj() mới; được trình biên dịch ủy quyền nếu Obj triển khai MyInterface. myObj chỉ có thể gọi các phương thức MyInterface. Tương tự cho dòng thứ hai.

Dưới đây là một số mẫu mã để thử:

public class Test { 

    public static void main(String args[]){ 
      A a = new A(); 
      a.say(); 
      a.a(); 

      B b = new B(); 
      b.say(); 
      b.b(); 

      I ia = new A(); 
      ia.say(); 
      ia.a(); // fail 
    } 

} 

interface i { 
    public void say(); 
} 

class A implements i { 
    public void say(){ 
     System.out.println("class A"); 
    } 
    public void a(){ 
     System.out.println("method a"); 
    } 
} 

class B implements i { 
    public void say(){ 
     System.out.println("class B"); 
    } 
    public void b(){ 
     System.out.println("method b"); 
    } 
} 
+0

nhờ kbdjockey cho câu trả lời của bạn: okay, nhưng nếu chúng ta bắt đầu dự án mà không có giao diện, và sau đó chúng ta muốn thực hiện một giao diện vì chúng ta cần thêm các phương thức để thêm vào các lớp 'A' và' B': chúng ta sẽ mất các phương thức trước đó từ 'A' và' B' vì chúng ta sẽ khai báo 'a' và' b' làm đối tượng của tôi ... – Paul

+0

Chỉ vì 'A' và' B' thực hiện 'I' không có nghĩa là bạn phải khởi tạo chúng như vậy. Bạn vẫn có thể nói 'A myObj = new A()', và truy cập tất cả các phương thức 'A' (bao gồm cả các phương thức overriden từ' I'). –

0

Một loại suy đơn giản:

Xem xét một Chef (Interface). Và có đầu bếp Trung Quốc (lớp) và đầu bếp người Mỹ (lớp). Bây giờ, có một khách sạn nhìn ra ngoài để tuyển dụng một đầu bếp dựa trên một số tiêu chí như

  • có thể nấu không chay
  • có thể nấu chay
  • có kinh nghiệm 5 năm

Ở đây, tính đủ điều kiện là bối cảnh trong đó người đầu bếp kiểu được đánh giá (chức năng loại). Bây giờ, có thể có trường hợp đầu bếp Trung Quốc cũng có thể nấu thức ăn biển, các món ăn Ý, vv có thể là trường hợp với đối tác Mỹ. Tất cả những điều này có vẻ không liên quan đến quản lý khách sạn vì anh ta chỉ quan tâm đến các tiêu chí bắt buộc.

Đầu bếp làm việc trong khách sạn tương tự như đối tượng kiểu đầu bếp được sử dụng trong mã. Công việc hiển nhiên sẽ là nấu thức ăn thuần chay và không thuần chay (tiêu chí hoặc phương pháp giao diện). Điều đó không có nghĩa là Khách sạn không thể sử dụng kỹ năng làm thức ăn biển của đầu bếp Trung Quốc.

Chỉ là vấn đề xác định những kỹ năng (chức năng) mà Khách sạn đang tìm kiếm.

Hy vọng bạn sẽ có được ý tưởng.

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