2012-01-10 38 views
6

Điều gì sẽ xảy ra khi một lớp cha có trường được đánh dấu cuối cùng, nhưng ghi đè lên lớp con (ẩn?) Trường này? 'Cuối cùng' không dừng lại, phải không? Ví dụ cụ thể mà tôi đang làm là một lớp Xây dựng, từ đó các loại tòa nhà khác nhau được kế thừa. Chi phí của từng loại, trong số những thứ khác, phải là cuối cùng cho mỗi phân lớp, nhưng mỗi loại tòa nhà phải có chi phí riêng.Thừa kế các trường cuối cùng trong Java?

Chỉnh sửa: Tôi đã nhận ra rằng tôi không biết mình đang nói gì ở trên. Những gì tôi thực sự muốn là các biến tĩnh của chi phí. Tuy nhiên, nếu tôi khai báo các biến tĩnh này trong lớp cha, chúng sẽ là tĩnh đối với lớp cha, vì vậy Subclass1.cost, ví dụ, tham chiếu đến cùng một giá trị như Superclass.cost hoặc Subclass2.cost. Làm thế nào tôi có thể tạo các biến tĩnh cho mỗi lớp con, mà không cần khai báo chúng trong mỗi lớp.

+0

Tận dụng tối trường riêng tư. –

+0

Điều gì đó giống như thay đổi chi phí theo thời gian? Tại sao làm cho nó cuối cùng. Tôi không nghĩ rằng ẩn một lĩnh vực là một ý tưởng tốt. –

Trả lời

11

Từ khóa final, khi áp dụng cho các lĩnh vực của một lớp Java, không có gì để làm với thừa kế. Thay vào đó, nó chỉ ra rằng bên ngoài của hàm tạo, trường đó không thể được gán lại.

Java xử lý việc ẩn tên và ghi đè riêng biệt. Ghi đè thực sự thay đổi hành vi quan sát của chương trình khi chạy bằng cách chuyển đổi chức năng nào được gọi, trong khi ẩn tên thay đổi chương trình bằng cách thay đổi cách diễn giải tĩnh của trường nào đang được tham chiếu. final như được áp dụng để ghi đè chỉ hoạt động cho các phương thức, vì các trường trong Java không thể bị ghi đè. Việc sử dụng final trong các ngữ cảnh khác nhau này hơi khó hiểu một chút, không may là không có cách nào để ngăn chặn trường bị ẩn tên trong một lớp con.

Nếu bạn muốn các tòa nhà có chi phí khác nhau, một tùy chọn sẽ là có phương pháp bị ghi đè getCost được ghi đè khác nhau trong mỗi lớp dẫn xuất. Ngoài ra, bạn có thể có một trường đơn lẻ protected hoặc private trong lớp cơ sở lưu trữ chi phí, sau đó đặt từng trường con trực tiếp (nếu đây là protected) hoặc thông qua trình tạo lớp cơ sở (nếu trường này là private).

Hy vọng điều này sẽ hữu ích!

+0

Vì vậy, bạn đang nói làm cho trường được bảo vệ trong siêu lớp, sau đó chỉ được gán các giá trị khác nhau tự động trong hàm tạo lớp con? Nghe có vẻ hợp lý. – TheTedinator

+1

@TheTedinator - Điều này sẽ hoạt động nếu bạn từ bỏ công cụ sửa đổi 'final' cho trường. Nếu trường là 'final', nó không thể được gán các giá trị khác nhau trong hàm tạo lớp con. Thay vào đó, hàm tạo của lớp con sẽ phải chuyển giá trị lên đến hàm tạo của lớp bậc trên được chỉ định (như tôi đã trình bày trong câu trả lời của tôi). Nếu siêu lớp không gán một giá trị trong hàm tạo của nó, thì mã sẽ không biên dịch; nếu hàm tạo của lớp con cố gắng đặt giá trị của trường 'final' từ một lớp cha, mã sẽ không biên dịch. –

+0

@templatetypedef "nó chỉ ra rằng bên ngoài của hàm tạo, trường đó không thể được gán lại" không thực sự chính xác: Một trường cuối cùng không thể được gán lại, ngay cả trong hàm tạo. Do đó, một hàm tạo lớp con không thể ghi đè trường cuối cùng từ lớp cha như Ted Hopp đã nói. – Sebastian

3

Bạn có thể thực hiện theo hai cách sau: tạo một hàm truy nhập và ẩn trường đó hoặc chuyển chi phí xây dựng khác cho hàm tạo siêu lớp từ lớp con. Bạn có thể kết hợp những điều này và làm cho một tài sản mà không thể được ghi đè bởi lớp con:

public class Building { 
    private final int cost; 

    protected Building(int cost, ...) { 
     this.cost = cost; 
    } 

    public final int getCost() { 
     return cost; 
    } 
} 

public class Cottage extends Building { 
    public Cottage() { 
     super(COTTAGE_COST, ...); 
    } 
} 
1

Đồng ý với câu trả lời khác, nhưng tôi nghĩ rằng việc thực hiện sau đây là tốt hơn trong trường hợp này:

public abstract class Building { 

     private final int cost; 

     public Building(int cost) { 
      this.cost = cost; 
     } 

     public final int getCost() { 
      return cost; 
     } 
    } 

    class Skyscraper extends Building { 
     public Skyscraper() { 
      super(100500); 
     } 
    } 

Tất nhiên lĩnh vực này có thể được công bố, nhưng đó là những câu chuyện khác ...

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