我试过下面的例子,它工作正常。
我希望它能够选择子类的值,因为不会为超类创建对象(因为它是抽象的)。但它只是在提升超级类别的场值。
请帮助我理解这背后的概念是什么?
abstract class SuperAbstract {
private int a = 2;
public void funA() {
System.out.println("In SuperAbstract: this.a " + a);
}
}
class SubClass extends SuperAbstract {
private int a = 34;
}
我打电话给new SubClass.funA();
我期待它打印34,但它打印2。
P.S .: 我想知道的是为什么在抽象类中使用它而不给我一个错误?
如下文所示,强调this
将对实例起作用,而抽象类不会有实例。
在实例方法或 构造函数,这是一个引用 当前对象 - 其对象 正在调用方法或构造函数。 你可以参考任何一个成员 实例中的当前对象 方法或构造函数使用它。 来自:http://java.sun.com/docs/books/tutorial/java/javaOO/thiskey.html
答案 0 :(得分:25)
A)在这种意义上,您无法覆盖字段。字段“不是虚拟的”,就像方法一样。
来自Java快速参考:Overloading, Overriding, Runtime Types and Object Orientation - Overriding Methods
- 字段无法覆盖,但可以隐藏,即如果在子类中声明一个与超类中的字段同名的字段,则只能使用super或超类访问超类字段输入
B) 如果你可以,那么该字段可能必须至少受到保护: - )
因为不会为超类创建对象(因为它是抽象的)
实际上是实例化的。
abstract
关键字仅确保在实例化时,它以子类的形式实例化。实例化Dog
时,您同时实例化Animal
! this
上下文中的Animal
引用将始终引用Dog
或Cat
或其他任何内容,但在所有情况下都引用某些Animal
this
}。 : - )
如下例所示,即使在抽象类中,abstract class Animal {
public String name;
public Animal(String name) {
System.out.println("Constructing an Animal");
this.name = name;
}
public abstract void speak();
}
class Dog extends Animal {
public Dog(String name) {
super(name);
System.out.println(" Constructing a Dog");
}
public void speak() {
System.out.println("Bark! My name is " + name);
}
}
public class Test {
public static void main(String... args) {
new Dog("Woffy").speak();
}
}
引用也是有意义的:
Constructing an Animal
Constructing a Dog
Bark! My name is Woffy
打印:
this
更新: public Animal getSuperThis() { return this; }
引用引用超类中与子类中相同的对象。
您可以尝试添加
System.out.println(this == getSuperThis());
到动物类,然后做
Dog.speak()
{{1}}中的。你会看到它打印为真。
答案 1 :(得分:11)
在类中声明的任何字段都是唯一的,即使它与基类中的字段具有相同的名称(即只能覆盖方法,但不能覆盖字段)。因此,派生类中有两个不同的字段:SuperAbstract.a
和SubClass.a
。基类为abstract
的事实没有影响。
abstract
关键字只表示无法实例化某个类,即您无法编写new SuperAbstract()
。您只能实例化子类的对象,该对象必须覆盖标记为abstract
的所有方法。
答案 2 :(得分:1)
您提供的代码包含变量a
作为SuperAbstract
类的私有成员。因为,您似乎没有覆盖该函数,它表示来自SuperAbstract
类的代码,并且执行它将访问类本身中声明的a
,无论它是什么从任何继承的类调用。要访问后面变量的值,需要通过在派生类中再次定义函数来覆盖该函数。最终代码如下所示:
abstract class SuperAbstract {
protected int a = 2;
public void funA() {
System.out.println("In SuperAbstract:" + this.a);
}
}
class SubClass extends SuperAbstract {
private int a = 34;
//Overriding the above function
public void funA() {
System.out.println("In SubClass: " + a);
//Or even check using the super keyword
System.out.println("In SubClass with super: " + super.a);
//Now call the function to display the value of a from SuperAbstract
super.funA();
}
}
在上面的代码中,我将a
更改为protected,以便也可以从派生类访问它。