我在Java语言中有两个类A和B,A扩展了B,并且它们在构造函数中都有一个具有相同名称的属性。
我正在尝试访问类B的属性name
的值,但是当从A创建新对象时,它被A替换。
class B {
constructor(){
this.name = "I AM B"
}
speakB(){
return this.name
}
}
class A extends B {
constructor(){
super()
this.name = "I AM A"
}
speakA(){
return this.speakB() + " and " + this.name;
}
}
var b = new B();
console.log(b.speakB()) //I AM B
var a = new A();
console.log(a.speakA()) //I AM A and I AM A
按预期结果,我希望获得I AM B and I AM A
,但我得到I AM A and I AM A
。我也尝试过super.speakB() + " and " + this.name;
,但没有成功。
在声明类时是否缺少某些内容?
答案 0 :(得分:4)
当您用派生类扩展一个类,然后实例化派生类时,那里只有一个对象。无论代码位于哪个类中,this.name
都指向该对象的相同this
和相同属性。
这里的关键是只有一个对象,基类和派生类都将其设置为属性。因此,如果您使用相同的命名属性,则无论是哪个基类或派生类对其进行设置,其值都将相同。
这样想:
let obj = new A();
obj.name = "Bob";
只有一个对象具有一个.name
属性。 A和B的方法都在同一个对象上操作,因此在方法A和B中使用相同的属性名称将设置完全相同的属性。
执行此操作时:
this.name = "I AM A".
在派生类中,您将覆盖父B为.name
属性设置的先前值。
这意味着我不能为两个类使用相同的属性名称吗?
正确,如果您希望两个属性具有单独的值,则不正确。注意,在很多情况下,派生类想访问基类设置的属性,因此这也是一个功能。但是,如果您打算将两个属性分别用于基本属性和派生属性,则必须给它们指定不同的名称。
对于某些人来说,一个可能引起混淆的原因是,通过class
语法声明的方法对于每个类都是分开的。每个类都有自己的原型对象,并且在链中搜索原型以解析方法。即使基类和派生定义了相同的命名方法,这也允许您专门调用基类方法。
但是,对于常规实例属性分配this.x = "foo"
而言,情况并非如此,因为它们是分配给实例对象而不是原型对象的。请记住,原型在所有对象实例之间共享,因此您不能在实例上存储实例状态。