2013-09-06 27 views
21

Xét đoạn mã sau:Sử dụng một phương pháp tùy tiện xác định một giao diện vô danh

public static void main(String[] args) { 
    File file = new File("C:\\someFile.txt") { 
     public void doStuff() { 
      // Do some stuff 
     } 
    }; 

    file.doStuff(); // "Cannot resolve method" 
} 

Khi chúng tôi cố gắng gọi phương thức mới định nghĩa của chúng tôi doStuff(), nó không phải là có thể. Lý do cho điều này là file được khai báo là một đối tượng thuộc loại File và không phải là một thể hiện của lớp con ẩn danh mới của chúng tôi.

Vì vậy, câu hỏi của tôi là, có cách nào tốt đẹp để đạt được hành vi này không? Khác với hiển nhiên (chỉ là, khai báo lớp đúng cách).

+3

http://stackoverflow.com/questions/8697971/anonymous-class-method-access - Bạn sẽ không "trọng" bất cứ điều gì ở đây, đó là việc sử dụng thông thường hơn của các tầng lớp vô danh, vì vậy phương pháp của bạn sẽ chỉ có sẵn trong lớp ẩn danh của bạn hoặc nếu bạn đã làm một cái gì đó bằng cách sử dụng phản ánh –

+0

'extend' là đủ tốt cho tôi. –

+0

Bạn có thể sử dụng một lớp ẩn danh nhưng bạn không thể có giao diện ẩn danh. –

Trả lời

16

Điều đó là không thể, vì bạn đang cố gắng gọi lớp con phương thức trên tham chiếu siêu lớp. Và phương pháp đó không được định nghĩa trong chính lớp siêu. Lớp ẩn danh chỉ là một lớp con của File ở đó.

Tuy nhiên, một cách giải quyết là phải đi qua phản ánh:

file.getClass().getMethod("doStuff").invoke(file); 

Phương pháp getClass() sẽ trả về kiểu thời gian chạy của file, và sau đó bạn có thể nhận được phương pháp cho các lớp học rằng việc sử dụng phương pháp Class#getMethod().

Vâng, tôi không phải là một fan hâm mộ lớn của sự phản ánh bản thân mình. Dĩ nhiên, cách tốt hơn là tạo một lớp bằng cách mở rộng lớp học siêu hạng, nếu bạn định làm những thứ này. Nó sẽ thực sự là một nỗi đau trong đầu, làm việc theo cách của bạn ra bằng cách sử dụng sự phản ánh, cho những gì có thể dễ dàng thực hiện bằng cách sử dụng một sửa đổi đơn giản.

+0

'file.getClass(). GetMethod (" doStuff "). Gọi();' không hoạt động ở đây. –

+0

@Ruchira. Ý bạn là như thế nào? –

+0

RE: Chỉnh sửa của bạn về những nguy hiểm của sự phản chiếu: Đó là tốt, tôi sẽ không bắt đầu sử dụng sự phản chiếu ở khắp mọi nơi. Đây hoàn toàn là một câu hỏi 'lý thuyết', và đây là câu trả lời hay nhất. – Xenoprimate

7

Cách tốt nhất là không sử dụng lớp bên trong vô danh trong trường hợp của bạn nhưng xác định lớp của riêng bạn mở rộng File và thêm bất kỳ phương pháp nào bạn cần ở đó.

class StuffedFile extends File { 
    // implement all needed constructors 
    public void doStuff() { /*.....*/} 
} 

Bây giờ bạn có thể sử dụng nó như sau:

MyFile f = new MyFile("..."); 
f.doStuff(); 

Tuy nhiên toàn bộ nỗ lực này để mở rộng File không âm thanh như một thiết kế tốt. Tạo lớp khác có thể chấp nhận tệp và thực hiện các công cụ trên đó. Bạn sẽ đạt được sự đóng gói và tái sử dụng mã tốt hơn.

EDIT Rõ ràng bạn có thể sử dụng sự phản chiếu để gọi bất kỳ phương pháp nào bạn muốn nhưng tôi không thể gọi đây là "giải pháp tốt đẹp". Tôi có thể gọi đây là "cách giải quyết có thể".

+0

Mã chỉ là một ví dụ, tôi không làm bất cứ điều gì với File. Ngoài ra tôi đã tìm kiếm một cú pháp 'sạch hơn' mà không cần phải tạo một lớp mới. Tôi biết rằng tôi chỉ có thể mở rộng Tệp. – Xenoprimate

+5

+1 để không đề xuất phản ánh –

+1

Nó sẽ không rõ ràng hơn, để thay đổi MyFile thành lớp đã định nghĩa StuffedFile? – Timo

2

gần nhất tôi đã có thể để có được đến cấp độ của bạn của tính cô đọng là:

public static void main(String[] args) { 
    abstract class FileThatDoesStuff extends File { 
    // Need a constructor that takes a String because File has one. 
    public FileThatDoesStuff(String filePath) { 
     super(filePath); 
    } 
    // It also does stuff. 
    public abstract void doStuff(); 
    } 
    FileThatDoesStuff file = new FileThatDoesStuff("C:\\someFile.txt") { 
    @Override 
    public void doStuff() { 
     // Do some stuff 
    } 

    }; 
    file.doStuff(); // "Can resolve method" 
} 

Tôi phải thừa nhận tôi ước gì có thể làm:

abstract class DoesStuff<T> extends T { 
    public abstract void doStuff(); 
} 
+0

Curmudgeon: C# cung cấp phương thức này với các phương thức mở rộng (hành vi cuối cùng bạn nêu ở đó). Một trong những lý do tôi yêu C# :) – Xenoprimate

0

Có thể truy cập vào phương pháp mà . Nhưng tôi không biết tại sao bạn lại muốn làm điều này.

public static void main(String[] args) { 
    new File("C:\\someFile.txt") { 
     public void doStuff() { 
      // Do some stuff 
     } 
    }.doStuff(); 
} 
Các vấn đề liên quan