先看一段代码,猜猜结果是什么。
public class People2 {
String name;
public People2(String name) {
this.name = name;
}
void test1() {
System.out.println(this.name);
}
public static void main(String[] args) {
// 是输出zyt还是People2
// 换为super(name)就没问题了
new Student2("zyt").test1();
}
}
class Student2 extends People2 {
String name;
public Student2(String name) {
super("People2");
this.name = name;
}
}
答案肯定是People2.
以前没有注意到这个问题哦,我是在kotlin语法中注意到这个问题,然后用JAVA试了一下也一样。kotlin代码如下
open class People(
private val name: String
) {
constructor() : this("People")
fun funOfPeople(people: People) {
println(people.javaClass) // 这里并没有问题
// 当传入的参数是People的子类时,如果子类的属性和People的属性一样
// 也不会调用子类的属性,除非子类覆盖People中名字相同的属性
println(people.name)
}
fun fun2OfPeople() {
// 这里也会出现同样的问题
// 子类实例调用父类方法的,虽然this的类型是子类型
// 但是当属性名子一样时,还是会调用父类的属性
// 原因:因为在kotlin中类的属性是final的,子类不可以覆盖,
// 那么我们在调用this.name时,肯定就是引用的父类中的属性,
// 调用的是主构造器中的属性值
// 解决方法和上面一样
println(this.name)
}
}
class Worker(
val name: String
) : People()
fun main() {
val worker1 = Worker("zyt")
val people = People("shx")
people.funOfPeople(worker1) // 为什么不是zyt
}
解决:
open class People(
// 这里改为open,因为kotlin属性默认为final(子类不可覆盖)
open val name: String
) {
constructor() : this("People")
fun funOfPeople(people: People) {
println(people.javaClass)
println(people.name)
}
fun fun2OfPeople() {
println(this.name)
}
}
class Worker(
// 当子类属性名字一样时,需要添加override关键字
override val name: String
) : People()