前言:写代码要抽象,抽象-具体就牵涉到继承,在做项目的过程中,如果许多子类都拥有相同的实现的方法和属性,就会把它们提取到一个共同的父类中,可是在使用过程中,我产生了一些疑惑,比如:子类如果重写了父类的属性是怎么样的结果?于是有了下面的一系列例子来探究。
栗子1
父类和子类都拥有相同的属性,用多态的方式声明,定义为子类,属性属于谁?
//Father.java
public class Father {
public String name = "Father";
}
//Son.java
public class Son extends Father {
public String name = "Son"; //子类重写了属性
}
//Main.java
public static void main(String[] args) {
//test 1
Father son = new Son(); //多态
System.out.println("son --- " + son.name);
//test 2
Son son1 = new Son();
System.out.println("son1 --- " + son1.name);
}
输出结果:
son --- Father
son1 --- Son
【栗子1说明】属性不具备多态性,谁定义的实例,属性就是属于谁。
栗子2
父类和子类拥有相同的属性,父类有个获得该属性的方法,子类调用会得到谁的属性?
//Father.java
public class Father {
public String name = "Father";
//父类加了一个方法
public void printName() {
System.out.println("Father: ---" + name);
}
}
//Son.java
public class Son extends Father {
public String name = "Son"; //子类只重写了属性
}
//Main.java
public static void main(String[] args) {
//test 1
Father son = new Son();
son.printName(); //调用父类方法打印
//test 2
Son son1 = new Son();
son1.printName(); //调用父类方法打印
}
输出结果:
Father: --- Father
Father: --- Father
【栗子2说明】子类默认继承父类的方法,如果不重写该方法,里面使用的是变量是父类的变量
【扩展说明】这就是好比为什么我们写一个BaseView
的时候,在onCreate()
里面用的不是setContentView(R.layout.mainXXX)
,而是setContentView(getContentViewRes())
,然后由子类去重写int getContentViewRes()
方法即可。
栗子3
在栗子2的基础上,子类重写父类的方法
//Father.java
public class Father {
public String name = "Father";
public void printName() {
System.out.println("Father: --- " + name);
}
}
//Son.java
public class Son extends Father {
public String name = "Son";
//子类重写了printName方法
public void printName() {
System.out.println("Son: --- " + name);
}
}
//Main.java
public static void main(String[] args) {
//test 1
Father son = new Son();
System.out.println("--- son name is " + son.name);
son.printName(); //调用子类方法打印
System.out.println("--- son name is " + son.name);
//test 2
Son son1 = new Son();
System.out.println("--- son1 name is " + son1.name);
son1.printName(); //调用子类方法打印
System.out.println("--- son1 name is " + son1.name);
}
输出结果:
--- son name is Father
Son: --- Son
--- son name is Father
--- son1 name is Son
Son: --- Son
--- son1 name is Son
【栗子3说明】子类继承父类的方法,如果重写该方法,里面使用的是变量是自己的变量,即使是用多态定义的。
2、3的例子,我理解成,在谁
的方法中,就会调用谁
的属性。
栗子4
父类和子类拥有相同的属性,在父类方法中,有一个方法是改变属性的,那么子类调用是否会改变自己的属性?
//Father.java
public class Father {
public String name = "Father";
public void printName() {
System.out.println("Father: --- " + name);
}
//新加的方法
public void init() {
name = "父类";
}
}
//Son.java
public class Son extends Father {
public String name = "Son";
public void printName() {
System.out.println("Son: --- " + name);
}
}
//Main.java
public static void main(String[] args) {
//test 1
Father son = new Son();
System.out.println("--- son name is " + son.name);
son.init();
son.printName();
System.out.println("--- son name is " + son.name);
//test 2
Son son1 = new Son();
System.out.println("--- son1 name is " + son1.name);
son1.init();
son1.printName();
System.out.println("--- son1 name is " + son1.name);
}
输出结果:
--- son name is Father
Son: --- Son
--- son name is 父类
--- son1 name is Son
Son: --- Son
--- son1 name is Son
结果说明:第一个son
是由Father
类定义的,它的属性是Father
实例的属性,第二个son1
是由Son
类定义的,它的属性是Son
实例的属性。init()
方法是Father
的方法,改变的是Father
实例的属性。如果我们在init()
方法中加句打印System.out.println("name = " + name);
,那么两个实例都会打印一个结果name = 父类
。
【栗子4说明】根据结果我们发现,父类的init()
方法改变的还是父类的属性,再进一步验证前面的结果——在谁
的方法中,就会调用(使用/改变)谁
的属性。
栗子5
在栗子4的基础上,让子类重写父类的init()
方法,其他代码完全一样
//Father.java
public class Father {
public String name = "Father";
public void printName() {
System.out.println("Father: --- " + name);
}
public void init() {
name = "父类";
}
}
//Son.java
public class Son extends Father {
public String name = "Son";
public void printName() {
System.out.println("Son: --- " + name);
}
//子类重写父类init()方法
public void init() {
name = "子类";
}
}
//Main.java
public static void main(String[] args) {
//test 1
Father son = new Son();
System.out.println("--- son name is " + son.name);
son.init();
son.printName();
System.out.println("--- son name is " + son.name);
//test 2
Son son1 = new Son();
System.out.println("--- son1 name is " + son1.name);
son1.init();
son1.printName();
System.out.println("--- son1 name is " + son1.name);
}
输出结果:
--- son name is Father
Son: --- 子类
--- son name is Father
--- son1 name is Son
Son: --- 子类
--- son1 name is 子类
(测试到这我已经凌乱了……)
【栗子5说明】栗子5再次说明前面几点:
1.属性不具备多态性,谁定义的实例,属性就是属于谁。
2.除非用该类的方法(被重写了不算)更改该实例属性,否则属性不会改变。
3.哪个类的方法(被重写了不算)使用哪个类定义实例的属性
4.也是这篇博文的中心论证:
没事不要让子类重写父类的属性玩,好累……