2010-03-08 30 views
70

có thể tạo lớp bên trong trong giao diện không? Nếu có, tại sao chúng ta tạo ra như vậy? Dù sao chúng ta sẽ không tạo ra bất kỳ đối tượng giao diện nào?Lớp bên trong trong Giao diện

Họ có trợ giúp trong bất kỳ quy trình Phát triển nào không?

Trả lời

33

Có, bạn thể tạo cả một lớp lồng nhau hoặc một lớp bên trong bên trong một giao diện Java (lưu ý rằng trái với niềm tin phổ biến không có những điều như một "tĩnh lớp bên": đây chỉ đơn giản là làm cho không có ý nghĩa, không có lớp "bên trong" và không có "outter" khi lớp lồng nhau là tĩnh, vì vậy nó không thể là "static inner").

Dù sao, sau đây biên dịch tốt:

public interface A { 
    class B { 
    } 
} 

Tôi đã nhìn thấy nó được sử dụng để đặt một số loại "kiểm tra hợp đồng" trực tiếp trong định nghĩa giao diện (tốt, trong lớp lồng nhau trong giao diện, mà có thể có các phương thức tĩnh, trái ngược với chính giao diện, mà không thể). Nhìn như thế này nếu tôi nhớ chính xác.

public interface A { 
    static class B { 
     public static boolean verifyState(A a) { 
      return (true if object implementing class A looks to be in a valid state) 
     } 
    } 
} 

Lưu ý rằng tôi không bình luận về tính hữu ích của một thứ như vậy, tôi chỉ đơn giản trả lời câu hỏi của bạn: có thể thực hiện và đây là một loại sử dụng tôi đã thấy.

Bây giờ tôi sẽ không bình luận về tính hữu ích của một cấu trúc như vậy và từ tôi đã thấy: Tôi đã nhìn thấy nó, nhưng nó không phải là một cấu trúc rất phổ biến.

200KLOC codebase ở đây xảy ra chính xác thời gian (nhưng sau đó chúng tôi có rất nhiều thứ khác mà chúng tôi coi là hành vi xấu xảy ra chính xác không quá thời gian mà những người khác sẽ thấy hoàn toàn bình thường như vậy ...).

+0

Bạn có thể thêm một số ví dụ về cách sử dụng không? Tôi đã thử nghiệm một cái gì đó tương tự như một số thời gian trước đây và đã không hiểu những gì tôi có thể đạt được từ việc sử dụng xây dựng này. – Roman

+0

@Roman: tôi nhớ là tôi đã gặp phải điều này trên một số dự án (dự án tương đối sạch sẽ tôi thêm nhưng chúng không phải của tôi) nhưng tôi không biết nếu nó thực sự sạch sẽ hay không. Tôi đã thêm một ví dụ nhỏ trông giống như những gì tôi đã nhìn thấy nhưng một lần nữa: đây không phải là mã của tôi và tôi không sử dụng cấu trúc đó nên tôi không đủ điều kiện để đưa ra các ví dụ hợp lệ :) IIRC lớp bên trong luôn được đặt tên, ví dụ * StateChecker * và các cuộc gọi sẽ luôn như sau: * A.StateChecker.check (a) * hoặc một cái gì đó tương tự. – SyntaxT3rr0r

+4

Nếu bạn nói rằng "không có thứ gì như" * lớp bên trong tĩnh * "" câu trả lời của bạn rằng "bạn * có thể * tạo cả lớp lồng nhau hoặc lớp bên trong bên trong giao diện Java" về cơ bản là sai. Sử dụng định nghĩa thu hẹp của bạn, 'interface' có thể * không * có các lớp bên trong. Bạn có thể bỏ qua công cụ sửa đổi 'tĩnh' của lớp lồng nhau của' giao diện' nhưng vẫn là lớp lồng nhau, không phải là lớp bên trong. – Holger

37

Sử dụng hợp lệ, IMHO, là xác định các đối tượng được nhận hoặc trả về bằng các phương thức giao diện kèm theo. Cấu trúc nắm giữ dữ liệu về mặt ảo thuật. Theo cách đó, nếu đối tượng chỉ được sử dụng cho giao diện đó, bạn có mọi thứ theo cách gắn kết hơn.

By dụ:

interface UserChecker { 
    Ticket validateUser(Credentials credentials); 

    class Credentials { 
     // user and password 
    } 

    class Ticket { 
     // some obscure implementation 
    } 
} 

Nhưng dù sao ... nó chỉ là một vấn đề của hương vị.

8

Trường hợp sử dụng thú vị là cung cấp một loại thực hiện mặc định cho các phương thức giao diện thông qua lớp bên trong như được mô tả ở đây: https://stackoverflow.com/a/3442218/454667 (để khắc phục sự cố thừa kế một lớp).

1

Những gì @Bachi đề cập tương tự như các đặc điểm trong Scala và thực sự được triển khai bằng cách sử dụng một lớp lồng nhau bên trong một giao diện. Điều này có thể được mô phỏng trong Java. Xem thêm java traits or mixins pattern?

79

Có, chúng tôi có thể có các lớp bên trong giao diện. Một ví dụ về cách sử dụng có thể là

public interface Input 
{ 
    public static class KeyEvent { 
     public static final int KEY_DOWN = 0; 
     public static final int KEY_UP = 1; 
     public int type; 
     public int keyCode; 
     public char keyChar; 
    } 
    public static class TouchEvent { 
     public static final int TOUCH_DOWN = 0; 
     public static final int TOUCH_UP = 1; 
     public static final int TOUCH_DRAGGED = 2; 
     public int type; 
     public int x, y; 
     public int pointer; 
    } 
    public boolean isKeyPressed(int keyCode); 
    public boolean isTouchDown(int pointer); 
    public int getTouchX(int pointer); 
    public int getTouchY(int pointer); 
    public float getAccelX(); 
    public float getAccelY(); 
    public float getAccelZ(); 
    public List<KeyEvent> getKeyEvents(); 
    public List<TouchEvent> getTouchEvents(); 
} 

Ở đây mã có hai lớp lồng nhau để chứa thông tin về các đối tượng sự kiện sau này được sử dụng trong định nghĩa phương thức như getKeyEvents(). Có chúng bên trong giao diện đầu vào cải thiện sự gắn kết.

+8

Ví dụ thực sự tốt đẹp, điều này cần phải có nhiều upvotes! – Levit

+2

@Levit Chỉ cần tự hỏi, làm thế nào lớp thực hiện sẽ như thế nào? – overexchange

+0

Rất thích xem thực hiện hành động cho việc sử dụng ở trên. Cảm ơn bạn. –

19

Trích từ Java 7 spec:

Giao diện có thể chứa các khai báo loại thành viên (§8.5).

Tuyên bố loại thành viên trong giao diện hoàn toàn tĩnh và công khai. Nó được phép định nghĩa một hoặc cả hai công cụ sửa đổi này.

KHÔNG thể khai báo các lớp không tĩnh trong giao diện Java, điều này hợp lý với tôi.

+0

Cảm ơn bạn. Đây có lẽ là câu trả lời ngắn gọn nhất. – Joseph

7

Nó chắc chắn là có thể, và một trường hợp mà tôi đã thấy nó hữu ích là khi một giao diện phải ném ngoại lệ tùy chỉnh. Bạn giữ các trường hợp ngoại lệ với giao diện liên quan của họ, mà tôi nghĩ là thường neater hơn xả rác cây nguồn của bạn với đống các tập tin ngoại lệ tầm thường.

interface MyInterface { 

    public static class MyInterfaceException extends Exception { 
    } 

    void doSomething() throws MyInterfaceException; 
} 
6

Có thể có định nghĩa lớp tĩnh bên trong giao diện, nhưng có thể khía cạnh hữu ích nhất của tính năng này là khi sử dụng loại enum (loại đặc biệt của lớp tĩnh). Ví dụ: bạn có thể có một cái gì đó như thế này:

public interface User { 
    public enum Role { 
     ADMIN("administrator"), 
     EDITOR("editor"), 
     VANILLA("regular user"); 

     private String description; 

     private Role(String description) { 
      this.description = description; 
     } 

     public String getDescription() { 
      return description; 
     } 
    } 

    public String getName(); 
    public void setName(String name); 
    public Role getRole(); 
    public void setRole(Role role); 
    ... 
} 
0

Tôi tìm thấy một loại linh sam sử dụng loại cấu trúc này.

  1. Bạn có thể sử dụng cấu trúc này để xác định và nhóm tất cả các hằng số tĩnh cuối cùng.
  2. Vì đó là giao diện bạn có thể thực hiện việc này trên một lớp học.

Bạn có quyền truy cập vào tất cả các hằng số được nhóm; tên của lớp hoạt động như một không gian tên trong trường hợp này.

0

Bạn cũng có thể tạo ra "Helper" lớp tĩnh cho các chức năng chung cho các đối tượng mà thực hiện giao diện này:

public interface A { 
    static class Helper { 
     public static void commonlyUsedMethod(A a) { 
      ... 
     } 
    } 
} 
1

Có lẽ khi bạn muốn xây dựng phức tạp hơn như một số hành vi thực hiện khác nhau, hãy xem xét:

public interface A { 
    public void foo(); 
    public static class B implements A{ 
     @Override 
     public void foo(){ 
      System.out.println("B foo"); 
     } 
    } 
} 

Đây là giao diện của bạn và đây sẽ là người thực hiện:

public class C implements A { 
    @Override 
    public void foo(){ A.B b = new A.B(); b.foo(); } 


    public static void main(String[] strings) { 
     C c = new C(); 
     c.foo(); 
    } 
} 

Có thể cung cấp một số triển khai tĩnh, nhưng điều đó sẽ không gây nhầm lẫn, tôi không biết.

0

Tôi cần một ngay bây giờ. Tôi có một giao diện nơi thuận tiện để trả về một lớp duy nhất từ ​​một số phương thức của nó. Lớp này chỉ có nghĩa là làm vùng chứa cho các phản hồi từ các phương thức của giao diện này. Do đó, sẽ thuận tiện khi có định nghĩa lớp lồng nhau tĩnh, chỉ được liên kết với giao diện này, vì giao diện này sẽ là nơi duy nhất mà lớp container kết quả này được tạo ra trước đây.

0

Ví dụ traits (giao diện giống như smth với các phương thức đã triển khai) trong Groovy. Chúng được biên dịch thành một giao diện chứa lớp bên trong, nơi tất cả các phương thức được thực hiện.

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