2009-12-19 38 views
10

Có thể trả về một phương thức tĩnh một lớp không? Tôi sẽ giải thích ...Java: Lớp học trả về (Không phải là một trường hợp)

tôi có:

public class A { public static void blah(){} } 
public class B { } 

Tôi muốn tạo ra một phương pháp tĩnh trong B phù thủy trả A. Vì vậy, bạn có thể làm:

A.blah(); 

B.getA().blah(); 

này, mà không cần tạo một thể hiện của A. Chỉ cần sử dụng nó phương pháp tĩnh.

Điều này có khả thi không?

+1

hoặc đọc http://gbracha.blogspot.com/2008/02/cutting-out-static.html hoặc tìm hiểu C và sử dụng con trỏ hàm. –

+0

Không phải là một câu trả lời như vậy nhưng ... Scala sử dụng các đối tượng singleton thay cho các phương pháp tĩnh (mà thực sự không phải là rất hướng đối tượng). Nếu bạn đã sử dụng Scala sau đó bạn rất nhiều * có thể * làm điều này loại –

Trả lời

7

Đây là một bác bỏ các câu trả lời @ irreputable của:

public class B { 
    public static A getA(){ return null; } 
} 

B.getA().blah(); //works! 

It "công trình", nhưng có lẽ không phải theo nghĩa mà bạn mong đợi, và chắc chắn không phải một cách hữu ích. Hãy phá vỡ này xuống thành hai phần:

A a = B.getA(); 
a.blah(); 

Bản tuyên bố đầu tiên được trả lại một (null trong trường hợp này) thể hiện của A, và báo cáo kết quả thứ hai là bỏ qua ví dụ đó và gọi A.blah(). Vì vậy, các báo cáo này là thực sự tương đương với

B.getA(); 
A.blah(); 

hoặc (cho rằng getA() là tác dụng phụ phí), chỉ đơn giản

A.blah(); 

Và đây là một ví dụ minh họa này rõ ràng hơn:

public class A { 
    public static void blah() { System.err.println("I'm an A"); } 
} 

public class SubA extends A { 
    public static void blah() { System.err.println("I'm a SubA"); } 
} 

public class B { 
    public static A getA(){ return new SubA(); } 
} 

B.getA().blah(); //prints "I'm an A". 

... và điều này (tôi hy vọng) minh họa tại sao phương pháp này không giải quyết được vấn đề của OP.

2

Không, điều này là không thể. Bạn chỉ có thể trả về một tham chiếu đến một thể hiện của một lớp. Điều gần nhất bạn có thể nhận được là trả về một tham chiếu đến một biến kiểu Class. Câu hỏi đặt ra là: tại sao bạn muốn điều này? Bạn đang cố giải quyết vấn đề gì? Có thể có giải pháp tốt hơn.

2

Thậm chí nếu có thể, nó sẽ không được sử dụng nhiều. Cuộc gọi A.blah() không tạo ra phiên bản A. Đó là một phương pháp tĩnh mà không cần một ví dụ.

Và bạn không thể sử dụng giao diện để triển khai phương pháp tĩnh. Vì vậy, những gì nó nên được tốt cho?

6

Không thể thực hiện điều này. Bạn có hai lựa chọn:

  1. B.getA() trả về một thể hiện của A, và blah() sẽ là một phương pháp không tĩnh.

  2. Gọi trực tiếp A.blah().

+0

Có thể, nhưng không được khuyến khích. Xem câu trả lời này http://stackoverflow.com/questions/1932625/java-return-class-not-an-instance/1933573#1933573 –

+1

wow. điều này thật đáng ngạc nhiên .. – zedoo

1

Nếu bạn không muốn có một thể hiện của A, sau đó để B gọi blah() trực tiếp. I E.

class B { 
    void blah() { 
     A.blah(); 
    } 
} 
6

tôi sẽ đoán rằng lý do bạn hỏi này là bạn muốn B để trở lại nhiều lớp khác nhau với các hành vi khác nhau - không chỉ A.

Bạn có thể muốn sử dụng một giao diện cho những gì bạn đang làm thay thế.

interface IA { 
    void blah(); 
} 

public class B { 
    IA getA1() { 
    return new IA { 
     void blah() { 
      ...code... 
     } 
    } 
    } 
    IA getA2() { 
    ... 
    } 
    IA getA3() { 
    ... 
    } 
} 

myCallingMethod { 
    B.getA1().blah(); 
    B.getA2().blah(); 
    B.getA3().blah(); 
} 
0

Bạn có thể trả về Phương thức sử dụng phản chiếu mà bạn có thể gọi() sau. Tuy nhiên, có vẻ như bạn đang cố gắng làm điều gì đó nên được thực hiện theo cách khác. Tại sao bạn lại cố gắng làm điều này?

4

Mọi người đang nói điều đó là không thể, và đó là loại đúng, nhưng nếu bạn sử dụng API phản chiếu, bạn có thể làm điều gì đó gần đó.

Đây là cách bạn có thể thực hiện.

Bạn có một lớp học thực hiện việc này.

public class B { 
    Class a 
    public static Class getA(){ 
     return a; 
    } 
} 

sau đó gọi blah bạn làm:

try{ 
    Method m = B.getA().getDeclaredMethod("blah"); 
    m.invoke(null);//for a static method, you can invoke on null 
} 
Catch(Exception e){ 
    // see documentation for list of exceptions 
} 

Vì vậy, tại sao bạn sẽ muốn làm điều này? Vâng, nếu bạn làm theo cách này bạn có thể thay đổi lớp A tại So getA() có thể trả về A, B, C hoặc D, tất cả đều có các hàm blah() khác nhau. Tôi không thực sự chắc chắn rằng mục đích sẽ phục vụ, nhưng nếu bạn muốn làm điều đó, bạn có thể.

xem: Class.getDeclaredMethod()Method.invoke() để biết thêm thông tin.

Tôi chưa thử điều này, vì vậy bạn có thể cần thực hiện một số chỉnh sửa.

1
public class B { 
    public static A getA(){ return null; } 
} 

B.getA().blah(); //works! 

EDIT

Đúng là nó tương đương với

B.getA(); 
A.blah(); 

Trừ họ trông khá khác nhau. Hãy tưởng tượng bạn có một chuỗi những thứ này.

Tôi đã kiểm tra org.apache.commons.cli.OptionBuilder và nhân cách tôi sẽ không làm theo cách đó, nhưng tác giả có trường hợp của anh ấy. API chỉ được sử dụng trong phần đầu của một chương trình, trong một chuỗi đơn.

Nhà thiết kế API đôi khi phải thực hiện một số động tác kỳ diệu, đừng quá phán xét.

+0

+1 để tìm lỗ hổng này trong Java.-1 cho không ném một lời cảnh cáo rằng điều này không nên được thực hiện. BTW, Eclipse tạo ra cảnh báo này khi biên dịch mã này 'Phương thức tĩnh blah() từ loại A sẽ được truy cập theo cách tĩnh'. –

+0

'org.apache.commons.cli.OptionBuilder' sử dụng kiểu chống gọi các phương thức tĩnh này trên các thể hiện được trả về. –

+0

Đây không phải là lỗ hổng trong Java. Nó chỉ là một ví dụ mà không làm những gì bạn nghĩ rằng nó đang làm. Xem câu trả lời của tôi. –

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