2009-10-19 20 views
7

Tôi ngớ ngẩn tại sao điều này được phépsubclassing Nội Lớp từ Outer Lớp so với khác Nội Lớp

public class Foo { 
    class Bar extends Foo { 
    } 
} 

Tuy nhiên điều này là không được phép

public class Foo { 
    class Bar extends Foo { 
    } 

    class Fooey extends Bar { 
    } 
} 

Trình biên dịch thông báo rằng nó không thể tham khảo Fooey.this trước khi constructor supertype được gọi.

Và điều này được phép

public class Foo { 
    static class Bar extends Foo { 
    } 

    class Fooey extends Bar { 
    } 
} 

gì đang xảy ra ở đây? Và tôi có thể đi đâu để tìm thêm thông tin về cách thức hoạt động của lớp bên trong?

EDIT Tôi nghĩ đến cả hai ý tưởng khá nghèo; lớp bên trong mở rộng lớp bên ngoài và lớp bên trong mở rộng lớp bên trong tĩnh khác. Tôi đã không chắc chắn chính xác những gì đã xảy ra và làm thế nào tôi nên refactor này. Tôi đã kết thúc chỉ yanking ra các lớp bên trong và đóng gói chúng trong lớp bên ngoài.

+0

Kiểm tra câu hỏi này, khá chắc chắn rằng điều này trùng lặp nó: http://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class –

+0

Không phải là một bản dupe (ít nhất không phải là một). –

+0

Việc sử dụng lớp bên ngoài của lớp bạn đang mở rộng là gì? – Jorn

Trả lời

6

Trước hết: Đừng làm điều này loại. Đó là điều ác. Thực sự, Java 1.1 nên đã được chỉ định rất nhiều hạn chế hơn, IMO.

Có sự nhầm lẫn về việc this sử dụng từ phương thức khởi tạo Foo.Fooey. Bên ngoài này (Foo.this) sẽ hoạt động. Nhưng thực tế thisFoo nhưng không thể truyền cho superconstructor vì các quy tắc về việc sử dụng this trước khi superconstructor trả về (và bên cạnh việc có một cá thể bên ngoài cùng một cá thể như thể hiện bên trong được fecked up). Bên ngoài này trên siêu lớp "((Bar)this).this$0" (IIRC), cũng không thể truy cập được do hạn chế sử dụng this.

Giải pháp là rõ ràng. Rõ ràng thường là một điều tốt trong cuốn sách của tôi (trừ khi nó trở thành bản mẫu).

public class Foo { 
    class Bar extends Foo { 

    } 

    class Fooey extends Bar { 
     Fooey() { 
      Foo.this.super(); 
     } 
    } 
} 

Tốt hơn, không có lớp bên trong mở rộng lớp bên ngoài của riêng mình hoặc mở rộng bất kỳ lớp bên trong nào.

+0

+1 cho nhận xét đầu tiên của bạn. Nếu bạn phải tạo một hàm tạo một cách rõ ràng, vì trình mặc định không biên dịch, tôi muốn nói rằng bạn đang làm sai (thiết kế khôn ngoan). – Jorn

+0

Tom, cảm ơn câu trả lời. Tôi đã nghĩ ra cả hai ý tưởng khá nghèo nàn; lớp bên trong mở rộng lớp bên ngoài và lớp bên trong mở rộng lớp bên trong tĩnh khác. Tôi không chắc chuyện gì đang diễn ra. – sal

1

Câu trả lời của Tom Hawtin là chính xác.

Bạn cũng có thể xem java puzzler. Chương mẫu có chứa trường hợp này và một vài trường hợp "thú vị" khác mà bạn có thể muốn xem.

1

(Không thể nhận xét - Tôi cần 50 đại diện)

Tôi cũng bị xáo trộn rằng điều này được cho phép. Một lớp bên trong (không tĩnh) của một lớp bên ngoài thực sự là một thành viên của lớp bên ngoài đó. Đọc: một đối tượng bên trong là một thành viên của đối tượng bên ngoài của nó. (Ngẫu nhiên, mọi đối tượng bên ngoài phải sở hữu một vật thể bên trong nhưng điều này ngoài vấn đề.)

Tương tự tôi thích sử dụng là: hãy để Car là lớp bên ngoài và để Wheel là lớp bên trong. Mỗi cá thể của Car phải và có ít nhất một phiên bản là Wheel làm thành viên.

Bây giờ nó không có ý nghĩa khái niệm cho một lớp bên trong để mở rộng một lớp bên ngoài. Tôi không thể nghĩ về bất kỳ tình huống thế giới thực nào đòi hỏi một đối tượng là cả một thành viên và một loại đối tượng khác. Đặt Theorists sẽ gọi lại số Axiom of Regularity và hậu quả của nó.

Hãy suy nghĩ theo cách này: Hãy để Honda mở rộng Car và để Honda là một lớp bên trong được lồng bên trong Car. Điều bạn đang nói ở đây là mỗi đối tượng Hondalà một đối tượngCar (duh) và mỗi Car đối tượng có đối tượngHonda. Chỉ một trong các câu lệnh này có ý nghĩa, nhưng cả hai đều được cho là đúng trong Java.

Hoặc trở lại tương tự trước đó, bạn không nên để Wheel mở rộng Car vì sau đó một Wheel sẽ được một Car, và theo định nghĩa phải khác Wheel, mà bằng cách này là mộtCar và vì vậy phải Wheel và Amen mãi mãi và từng có. Việc xây dựng một đối tượng Car sẽ dẫn đến một vòng lặp vô hạn của các đối tượng lồng nhau.

Tôi rất thất vọng rằng điều này là hợp pháp và không tạo ra lỗi biên dịch.

+0

Hãy tưởng tượng bạn sẽ khó chịu như thế nào nếu bạn thấy nó trong mã sản xuất! – sal

+0

Nếu Honda mở rộng Ô tô, nó * không * có nghĩa là mỗi đối tượng Xe có một đối tượng Honda. – RAY

+0

@RAY: có nhưng nếu Honda được lồng trong xe (a.k.a. a "thành viên" của ô tô) thì nó * có nghĩa là mọi đối tượng xe có đối tượng Honda. – chharvey

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