可以在java中的抽象类中使用关键字“this”

时间:2010-06-09 07:03:05

标签: java abstract-class

我试过下面的例子,它工作正常。

我希望它能够选择子类的值,因为不会为超类创建对象(因为它是抽象的)。但它只是在提升超级类别的场值。

请帮助我理解这背后的概念是什么?

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

3 个答案:

答案 0 :(得分:25)

A)在这种意义上,您无法覆盖字段。字段“不是虚拟的”,就像方法一样。

来自Java快速参考:Overloading, Overriding, Runtime Types and Object Orientation - Overriding Methods

  
      
  • 字段无法覆盖,但可以隐藏,即如果在子类中声明一个与超类中的字段同名的字段,则只能使用super或超类访问超类字段输入
  •   

B) 如果你可以,那么该字段可能必须至少受到保护: - )


  

因为不会为超类创建对象(因为它是抽象的)

实际上是实例化的。

abstract关键字仅确保在实例化时,它以子类的形式实例化。实例化Dog时,您同时实例化Animalthis上下文中的Animal引用将始终引用DogCat或其他任何内容,但在所有情况下都引用某些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.aSubClass.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,以便也可以从派生类访问它。