2011-12-29 29 views
7

Đây có thể là một điều xấu để làm, như được thảo luận trong Can parent and child class in Java have same instance variable?. (Điều gì sẽ xảy ra nếu tên biến cha được thay đổi? Sau đó, nó sẽ không bị che khuất nữa.) Tuy nhiên, tôi vẫn tò mò liệu các biến khác nhau tĩnh/nonstatic sẽ bóng lẫn nhau. Một mặt tôi sẽ mong đợi họ là cùng một tên biến vì vậy sẽ được shadowed, nhưng mặt khác nó có vẻ như trình biên dịch có thể phân biệt giữa hai dựa trên tĩnh.Trong Java, nếu một lớp con che một biến cha mẹ tĩnh với một biến con instance, biến nào sẽ kế thừa các phương thức sử dụng?

+1

tôi cảm thấy rằng đây là một cái gì đó quan trọng để xem xét và có thể giúp đỡ người khác, vì vậy câu hỏi này là sử dụng, nhưng: ** Các bạn đã thử nó ** –

+4

Đang cố gắng nó là một chuyện, nhưng điều đó có thể biên dịch? phụ thuộc. Tôi tự hỏi nếu có một quy tắc dứt khoát về điều này trong đặc tả ngôn ngữ. –

Trả lời

4

Từ The Java Language Specification:

Nếu một tên biểu hiện bao gồm một đơn Định danh, sau đó phải chính xác một tuyên bố rõ ràng biểu thị hoặc là một địa phương biến, thông số hoặc trường trong phạm vi tại thời điểm Số nhận dạng xảy ra. Nếu không, một lỗi biên dịch sẽ xảy ra.

Nếu khai báo khai báo trường cuối cùng, ý nghĩa của tên là giá trị của trường đó. Nếu không, ý nghĩa của tên biểu thức là biến được khai báo bởi khai báo.

Nếu một phương thức trong siêu lớp tham chiếu đến một trường cụ thể (tĩnh hoặc cách khác) của lớp đó, chỉ khai báo của trường đó sẽ nằm trong phạm vi tại điểm đó; bất kỳ trường nào (tĩnh hoặc cách khác) của lớp con sẽ không nằm trong phạm vi. Do đó, phương thức sẽ luôn sử dụng trường siêu lớp, ngay cả khi một lớp con kế thừa nó và đổ bóng trường đó.

Câu trả lời này được viết lại hoàn toàn dựa trên hiểu biết mới của tôi về câu hỏi. Dưới đây là câu trả lời đầu tiên của tôi, giữ cho hậu thế.

Từ The Java Language Specification:

Tờ khai d của một trường, biến cục bộ, tham số phương pháp, constructor tham số tham số hoặc ngoại lệ xử lý tên n bóng tờ khai của bất kỳ lĩnh vực khác, địa phương biến, phương thức tham số , tham số hàm tạo hoặc tham số xử lý ngoại lệ có tên n nằm trong phạm vi tại đó d xảy ra trong phạm vi của d.

Điều này cho thấy rằng trình biên dịch được yêu cầu phải làm bóng các biến mẹ, bất kể tĩnh.

Lưu ý rằng không có điều nào trong số này phù hợp với phương pháp được thừa kế, luôn sử dụng biến ban đầu bất kể lớp con có đổ bóng chúng hay không. Tôi nghi ngờ đây không phải là những gì bạn muốn hỏi.

+1

Điều này thực sự là một câu trả lời cho những gì tôi đã cố gắng hỏi: "không có điều nào liên quan đến các phương thức kế thừa, luôn sử dụng các biến ban đầu bất kể một lớp con có đổ bóng chúng hay không". –

+0

Đặc tả ngôn ngữ có nói điều này không? Nếu vậy, ở đâu? Tôi đang cố gắng tìm nó. –

+0

@DougTreadwell Vâng, đúng vậy. Tôi đã chỉnh sửa câu trả lời của mình. – Taymon

0

Nhìn vào mã bên dưới. Nếu bạn muốn truy cập field từ ChildClass, nó sẽ sử dụng biến thành viên của chính nó. Nếu bạn muốn truy cập vào static field từ SuperClass, bạn phải gọi nó một cách rõ ràng bằng cách sử dụng SuperClass.field. `STATIC_FIELD`` có thể được truy cập trực tiếp vì không có sự mơ hồ đối với trình biên dịch.

public class SuperClass{ 
    static String field = "staticField1"; 
    static String STATIC_FIELD = "staticField2"; 

    //not possible to have a member field in this class -> compile error 
    //String field = "memberField"; is not possible 
    public SuperClass() { 
     System.out.println("field = " + field); 

    } 
    } 
    public class ChildClass extends SuperClass{ 
    String field = "memberField"; 

    public ChildClass() { 
     System.out.println("field = " + field);//access to member field 
     //need to explicitly call SuperClass.field to access the static variable 
     System.out.println("SuperClass.field = " + SuperClass.field); 
     //no need to do this when there is no amibiguity 
     System.out.println("STATIC_FIELD = " + STATIC_FIELD); 
    } 
    } 

Xem thêm 15.11.1 và 15.11.2 trong here và 8.3 trong here

+0

Tôi hiểu ý tưởng về bóng tối, nhưng phần quan trọng trong qusetion của tôi là "biến nào sẽ được thừa hưởng các phương thức sử dụng?". –

6

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

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

Một lĩnh vực tiềm ẩn có thể được truy cập bằng cách sử dụng một tên đủ điều kiện (nếu nó là tĩnh)

JVM Specification

Bạn có thể tham khảo "Dòng khai báo" phần.

+0

Cho đến nay đây là một trong những câu trả lời hay nhất, nhưng dường như chỉ tập trung vào bóng tối. Tôi sẽ không loại bỏ bất kỳ thông tin nào, nhưng có bất kỳ điều gì bổ sung trong đặc điểm kỹ thuật có thể chỉ ra rằng các phương thức kế thừa cũng sử dụng các trường của con không? –

+0

Có vẻ như bạn đã có câu trả lời cho điều này từ Taymon. – kosa

+0

+1 cho câu trả lời này vì nó đề cập rằng bạn vẫn có thể truy cập trường thông qua tên đủ điều kiện. – Bill

4

họ sẽ:

class Parent { 
    static String x="static in parent"; 
    String y="instance in parent"; 
} 
class Child extends Parent { 
    static String y="static in child"; 
    String x="instance in child"; 
    void foo() { 
     System.out.println("x "+x); 
     System.out.println("super.x " + super.x); 
     System.out.println("y "+y); 
     System.out.println("super.y " + super.y); 
    } 
} 
public class Main { 
    public static void main(String[] args) { 
     Parent parent=new Parent(); 
     Child child=new Child(); 
     System.out.println("Parent.x "+Parent.x); 
     System.out.println("parent.x "+Parent.x); 
     System.out.println("parent.y "+parent.y); 
     System.out.println("child.x "+child.x); 
     System.out.println("Child.y "+Child.y); 
     System.out.println("child.y "+child.y); 
     System.out.println("(Parent)child).x "+((Parent)child).x); 
     System.out.println("(Parent)child).y "+((Parent)child).y); 
     child.foo(); 
    } 
} 



Parent.x static in parent 
parent.x static in parent 
parent.y instance in parent 
child.x instance in child 
Child.y static in child 
child.y static in child 
(Parent)child).x static in parent 
(Parent)child).y instance in parent 
x instance in child 
super.x static in parent 
y static in child 
super.y instance in parent 
+1

Đăng đầu ra quá, để mọi người có thể tìm hiểu ý nghĩa của nó, hoặc là nhận xét nội dòng hoặc đầu ra được dán vào bên dưới – Bohemian

+0

Tôi hiểu ý tưởng về bóng tối, nhưng phần quan trọng trong qusetion của tôi là " ". –

+0

vui lòng xem chỉnh sửa –

0
public class Test { 

    public static int MYNUMBER = 5; 

    public Test() { 
    } 
} 

public class TestChild extends Test { 

    public int MYNUMBER = 8; 

    public TestChild() { 
    } 
} 

public class Main { 

    public static void main(String[] args) { 
     TestChild testChild = new TestChild(); 

     // This would print out 8 
     System.out.println("in main test child: " + testChild.MYNUMBER); 

     // This won't even compile if the MYNUMBER variable is overshadowed 
     // If the MYNUMBER variable is not overshadowed it 
     // would compile and 
     // print out 5 
     // If we make MYNUMBER static also on TestChild, 
     // it would compile and print out 8 
     System.out.println("in main TestChild.MYNUMBER " + TestChild.MYNUMBER); 

     // This would print out 5 
     System.out.println(Test.MYNUMBER); 
    } 

} 
+0

Tôi hiểu ý tưởng về bóng, nhưng phần quan trọng trong qusetion của tôi là "biến sẽ kế thừa các phương thức sử dụng ? ". –

+0

Các phương thức kế thừa sẽ sử dụng biến tĩnh của phụ huynh. Vì vậy, nếu chúng ta thêm vào lớp Test phương thức: public int doSomething() { \t \t return MYNUMBER; \t} doSomething sẽ trả về 5 mọi lúc. – Alex

0

Với trình biên dịch của Eclipse, các phương thức từ lớp cha sẽ vẫn sử dụng các biến thành viên từ lớp cha, chứ không phải các biến được tô bóng từ lớp con, như được hiển thị bên dưới. Đây chỉ là một phiên bản sửa đổi nhỏ của câu trả lời của thinksteep.

class Parent { 
    static String x ="static in parent"; 
    String y="instance in parent"; 

    void bar() { 
     System.out.println("x "+ x); 
     System.out.println("y "+ y); 
    } 
} 

class Child extends Parent { 
    static String y ="static in child"; 
    String x="instance in child"; 

    void foo() { 
     System.out.println("x "+x); 
     System.out.println("super.x " + super.x); 
     System.out.println("y "+y); 
     System.out.println("super.y " + super.y); 
    } 
} 

public class Main { 
    public static void main(String[] args) { 
     Parent parent=new Parent(); 
     Child child=new Child(); 
     System.out.println("Parent.x "+Parent.x); 
     System.out.println("parent.x "+Parent.x); 
     System.out.println("parent.y "+parent.y); 
     System.out.println("child.x "+child.x); 
     System.out.println("Child.y "+Child.y); 
     System.out.println("child.y "+child.y); 
     System.out.println("(Parent)child).x "+((Parent)child).x); 
     System.out.println("(Parent)child).y "+((Parent)child).y); 
     System.out.println("Member variable visibility in parent:"); 
     parent.bar(); 
     System.out.println("Member variable visibility in child:"); 
     child.foo(); 
     System.out.println("Member variable visibility in inherited methods:");   
     child.bar(); 

     System.exit(0); 
} 

/* Output: 
Parent.x static in parent 
parent.x static in parent 
parent.y instance in parent 
child.x instance in child 
Child.y static in child 
child.y static in child 
(Parent)child).x static in parent 
(Parent)child).y instance in parent 
Member variable visibility in parent: 
x static in parent 
y instance in parent 
Member variable visibility in child: 
x instance in child 
super.x static in parent 
y static in child 
super.y instance in parent 
Member variable visibility in parent methods: 
x static in parent 
y instance in parent 
*/ 
Các vấn đề liên quan