2013-01-01 34 views
6

thể trùng lặp:
The concept of shadowingJava xử lý các trường khi upcasting như thế nào?

Tôi đang bối rối về cách các lĩnh vực của các lớp được xử lý trong Java trong upcasting. Ví dụ:

class SuperClass 
{ 
    String myString = "String in SuperClass"; 

    public void myMethod() 
    { 
     System.out.println("Method in SuperClass"); 
    } 
} 

class SubClass extends SuperClass 
{ 
    String myString = "String in SubClass"; 

    public void myMethod() 
    { 
     System.out.println("Method in SubClass"); 
    } 
} 

class Question 
{ 
    public static void main(String[] args) 
    { 
     SuperClass test = new SubClass(); 
      // object test is an instance of SubClass 
      // but I am telling the compiler to treat it as SuperClass 

     test.myMethod(); 
     System.out.println(test.myString); 

    } 
} 

Output:

Method in SubClass 
String in SuperClass //Why is "String in SubClass" not used? 

Khi tôi tạo ra một đối tượng test nó là một thể hiện của lớp SubClass; tuy nhiên, tôi đang nói cho trình biên dịch xem nó là SuperClass. Tất cả mọi thứ rõ ràng với tôi về phương pháp làm việc: Tôi sẽ chỉ có thể sử dụng các phương pháp của SubClass, nếu một phương pháp nhất định được xác định cho SuperClass.

Tuy nhiên, tôi bị mất là lý do tại sao một trường của SuperClass được sử dụng khi tôi cố gắng truy cập myString của test. Kể từ test là một phiên bản của SubClass Tôi mong đợi myString được xác định trong SubClass để được sử dụng, tại sao điều này không xảy ra? Tôi đang thiếu gì?

Tôi biết rằng tôi có thể truy cập, myString của SubClass bằng cách sử dụng toán tử this. Ví dụ, tôi có thể xác định printMyString phương pháp trong SuperClass, và ghi đè lên nó với

public void printMyString() 
{ 
    System.out.println(this.myString); 
} 

Trong SubClass, vì vậy câu hỏi của tôi chủ yếu là về cách đến các lĩnh vực của SuperClass được sử dụng trong test. Có lẽ tôi đang thiếu một cái gì đó hiển nhiên?

Tôi đã cố tìm kiếm câu trả lời và chủ đề gần nhất tôi tìm thấy là Upcasting in Java and two separate object properties, mặc dù hữu ích nhưng nó không trả lời được câu hỏi của tôi.

Cảm ơn bạn trong Advance

+0

câu hỏi hay @Akavall –

Trả lời

7

Thuộc tính không thể quá tải như phương pháp.

test.myMethod(); 

đây gọi phương thức phụ thuộc vào loại của đối tượng thực tế. Ở đây đối tượng thuộc loại SubClass do đó phương thức của SubClass được gọi.

test.myString 

Trong khi truy cập vào các thuộc tính, nó phụ thuộc vào loại tham chiếu biến. Ở đây tham chiếu biến tức là test là loại SuperClass vì vậy thuộc tính từ SuperClass được truy cập.

Điều bạn đang tìm kiếm là class variable hiding/shadowing.

+0

Liên kết tốt, cảm ơn bạn. Phần quan trọng là: "Khi một biến cá thể trong một lớp con có cùng tên với một biến cá thể trong một lớp siêu, thì biến cá thể được chọn trong lớp đó là kiểu tham chiếu." – Akavall

+0

@Akavall: Ya bạn nhấn điểm :) – xyz

3

Các trường trong Java là chỉ ẩn và không thực sự bị ghi đè (điều đó không có nghĩa là chúng tôi sẽ gặp lỗi thời gian biên dịch trong khi thử điều này, thay vào đó chúng không bị ghi đè theo đúng nghĩa của nó).

Overriding có nghĩa là thành viên nên được gọi dựa trên thời gian chạy loại đối tượng và không dựa vào loại khai báo.

Nhưng ràng buộc cho các trường trong Java luôn tĩnh và do đó nó dựa trên loại được khai báo của tham chiếu đối tượng. Trong ví dụ bạn đã đưa ra, bằng cách khai báo biến lớp với tên 'myString' trong lớp SubClass bạn ẩn biến lớp mà nó sẽ thừa hưởng từ lớp cha của nó SuperClass có cùng tên 'myString'.

Java ngôn ngữ đặc tả:

Nếu lớp tuyên bố một lĩnh vực với một tên nào đó, thì khai của lĩnh vực đó được cho là ẩn bất kỳ và tất cả các truy cập tờ khai của các lĩnh vực có cùng tên trong superclasses và siêu kết nối của lớp học.

Một trường ẩn có thể được truy cập bằng cách sử dụng tên đủ điều kiện nếu nó là tĩnh hoặc bằng cách sử dụng biểu thức truy cập trường chứa từ khóa siêu hoặc một loại siêu lớp.

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