2011-09-28 42 views
30

Tôi muốn thay đổi cách thức một lớp thực hiện mà không cần ghi đè phương thức và chỉ ghi đè (hoặc mở rộng lý tưởng) lớp bên trong. Giả sử rằng tôi không thể thay đổi thực tế là tôi cần phải làm điều này (tôi đang sửa đổi một cơ sở mã nguồn mở hiện có và sẽ có ma sát để rút ra các lớp hoặc không có điều gì).Làm thế nào để ghi đè/mở rộng một lớp bên trong từ một lớp con?

public class A { 
    static class Thing { 
    public int value() { return 10+value2(); } 
    public int value2() { return 10; } 
    } 

    public String toString() { 
    Thing t = new Thing(); 
    return Integer.toString(t.value()); 
    } 
} 

public class B extends A { 
    static class Thing { 
    public int value2() { return 20; } 
    } 
} 

Mục tiêu của tôi là, chỉ thay đổi Thing, nhận B's toString() để trả về "30", hiện tại nó sẽ trả về "20". Lý tưởng sẽ là chỉ thay đổi giá trị của phương thức 2 (do đó không thay đổi bất kỳ phương thức nào khác), nhưng tôi không biết liệu điều này có thể thực hiện được hay không.

Cảm ơn

Trả lời

35

Tôi nghĩ bạn cần một phương pháp nhà máy cho việc này. Hãy xem xét ví dụ sau (bắt nguồn từ đoạn mã của bạn):

static class A { 
    static class Thing { 
     public int value() { 
      return 10 + value2(); 
     } 
     public int value2() { 
      return 10; 
     } 
    } 
    protected Thing createThing() { 
     return new Thing(); 
    } 
    public String toString() { 
     return Integer.toString(createThing().value()); 
    } 
} 

static class B extends A { 
    static class Thing extends A.Thing { 
     public int value2() { 
      return 20; 
     } 
    } 
    @Override 
    protected Thing createThing() { 
     return new Thing(); // creates B.Thing 
    } 
} 

public static void main(String[] args) { 
    System.out.println(new B()); 
} 

Output:

30 
+1

Có mỗi ounce thanh lịch tôi hy vọng. Cảm ơn! –

+3

Vì tôi không nhìn thấy nó lúc đầu, tôi muốn nhấn mạnh rằng điều này yêu cầu ghi đè createThing trong lớp bên ngoài. Tôi tin rằng không có cách nào để ghi đè lên các phương thức trong lớp bên trong của A "Thing" từ một lớp con của A. (Tôi muốn nghe khác) Thay vào đó bạn đang thay thế A.Thing với một B.Thing mới mà bóng trong không gian tên của B nhưng không hiển thị với các phương thức trong A. Để sử dụng, bạn phải cập nhật mọi tham chiếu từ lớp bên ngoài. –

2

Không thể chỉ thay đổi giá trị2. Vấn đề là các cuộc gọi 'mới' không được gửi động - 'mới' trong toString sẽ luôn tạo A :: Thing. Bạn có thể khắc phục điều này khi tạo một nhà máy: một cái gì đó như thế này:

public class A { 
    static class Thing { 
    public int value() { return 10+value2(); } 
    public int value2() { return 10; } 
    } 

    private Thing makeThing() { return new Thing(); } 


    public String toString() { 
    Thing t = new Thing(); 
    return Integer.toString(t.value()); 
    } 
} 

public class B extends A { 
    static class Thing extends A.Thing { 
    public int value2() { return 20; } 
    } 

    private Thing makeThing() { return new Thing(); } 

} 
+0

Bạn đang sử dụng C cú pháp đối tượng ++, không Java. – Thor84no

3

Bạn sẽ có thể mở rộng lớp bên trong với Thing mở rộng A.Thing. Miễn là nó có thể nhìn thấy trong phạm vi của bạn nó không phải là một vấn đề.

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