智渔课堂官方免费教程十四:Java面向对象三大特性之继承

时间:2020-12-24 19:23:32

继承

在已有类的基础上建立出新的类,新的类拥有父类中访问修饰符允许访问的数据和功能,并且可以扩展新的数据和功能。
语法格式:class 子类名 extends 父类名{}
任何一个类的*父类都是Object类,即使创建一个类没有使用关键字extends继承任何类,那么此时默认是继承Object类的

关键字super

1、 在子类中访问父类的成员
例如:
//调用父类中的属性
super.属性
//调用父类中的方法
super.方法();
如果父类和子类中的属性出现同名时,必须使用super.的方式才能访问父类中的属性;如果没有同名冲突,可以省略super,也可以使用关键字this.的方式访问父类中的属性
2、super([参数列表]) 访问父类中的构造方法;
如果子类的构造方法中没有显示的编写super([参数列表])访问父类构造方法,系统默认提供一个访问父类无参构造的语句(super(););如果自行编写,必须写在子类构造方法中的第一行,此时系统将不再提供super(); 
实例一:演示使用继承后,创建子类对象时构造方法的执行顺序
package characteristic.inherit.create_order;
/**
 * 使用extends关键字继承父类Father
 * 演示创建子类对象时构造方法执行的顺序
 * @author 学霸联盟 - 赵灿
 */
public class Son extends Father{
	// 子类私有的属性name
	private String sonName;

	// 无参构造方法
	public Son() {
		// 调用父类的构造方法,必须写在构造方法中的第一行
		super("张三");
		System.out.println("Son类的无参构造");
	}

	// 带参构造方法
	public Son(String name) {
		/*
		 * 不写也会默认调用父类的无参构造
		 * 如果父类中写了带参构造,而没有写无参构造
		 * 这样系统不会给父类提供无参构造
		 * 此时在子类中使用super()就会出错,而且子类中必须使创建构造方法
		 * 并在构造方法中用super(参数)去调用父类的构造方法
		 */
		super();//这句代码可以省略
		System.out.println("Son类的带参构造,名称:" + name);
	}

	public void printFatherProperty() {
		// 子类中可以继承父类中除private修饰以外的成员
		//可以使用super.成员
		System.out.println(super.defaultProperty);
		//当前类没有属性和父类属性重名的情况下,也可以使用this.成员
		System.out.println(this.protectedProperty);
		//当前类没有属性和父类属性重名的情况下,也可以省略this
		System.out.println(publicProperty);
		//调用父类的方法同样可以使用上述三种方式
		super.work();
	}
}
package characteristic.inherit.create_order;
/**
 * 用于演示使用继承后创建子类对象时构造方法的执行顺序
 * @author 学霸联盟 - 赵灿
 */
public class Father {
	// 私有属性name
	private String fatherName;
	// 声明四种访问权限的属性,用于测试子类中继承的情况
	private String privateProperty = "父类私有的属性";
	String defaultProperty = "父类默认的属性";
	protected String protectedProperty = "父类保护的属性";
	public String publicProperty = "父类公共的属性";

	// 无参构造
	public Father() {
		System.out.println("Father类的无参构造方法");
	}

	// 带参构造
	public Father(String name) {
		System.out.println("Father类的带参构造方法,名称:" + name);
	}

	// 创建一个工作的方法
	public void work() {
		System.out.println("父类中工作的方法");
	}
}
package characteristic.inherit.create_order;
/**
 * 测试继承
 * @author 学霸联盟 - 赵灿
 */
public class Test {
	public static void main(String[] args) {
		System.out.println("----- 调用子类的无参构造创建子类对象 -----");
		// 调用不同的构造方法创建子类对象
		Son son1 = new Son();
		System.out.println("----- 调用子类的带参构造创建子类对象 -----");
		Son son2 = new Son("儿子:李四");
		son2.printFatherProperty();
	}
}
运行结果:
----- 调用子类的无参构造创建子类对象 -----
Father类的带参构造方法,名称:张三
Son类的无参构造
----- 调用子类的带参构造创建子类对象 -----
Father类的无参构造方法
Son类的带参构造,名称:儿子:李四
父类默认的属性
父类保护的属性
父类公共的属性
父类中工作的方法
由结果可以看出创建子类Son的对象时,会先执行Father的构造方法,如果子类中没有写构造方法或子类的构造方法中没有显示的调用父类的某个构造方法,那么默认会访问父类的无参构造方法。
而Father类没有写继承哪个类,默认是继承Object类的。
子类中可以访问父类中的哪些成员,由访问修饰符规定的权限决定

方法的重写:@Override

简单的理解就是在子类中重新编写从父类中继承的方法。
满足重写的条件:
1、子类中和父类中的方法同名(方法名相同)
2、发生在有继承关系的两个类中
3、参数列表要相同
4、返回值类型要兼容
5、不可以缩小访问修饰符,但可以放大访问修饰符
6、只能重写访问修饰符允许访问的方法
实例二:用于演示子类重写父类方法后,不同引用指向子类对象时执行的不同结果
package characteristic.inherit.resources;
/** 
 * 用于演示子类重写父类方法后,不同引用指向子类对象时执行的不同结果
 * @author 学霸联盟 - 赵灿
 */
public class Father {
	//工作的方法
	public void work(){
		System.out.println("父亲在辛苦的工作");
	}
	//父类中玩的方法
	public void play(){
		System.out.println("带着儿子玩");
	}
}
package characteristic.inherit.resources;
/**
 * 继承父类Father
 * @author 学霸联盟 - 赵灿
 */
public class Son extends Father{
	//子类重写父类中玩的方法
	public void play(){
		System.out.println("儿子还小,只能跟着父亲玩");
	}
	//子类中特有的方法
	public void study(){
		System.out.println("儿子在学习");
	}
}
package characteristic.inherit.resources;
/**
 * 测试继承
 * @author 学霸联盟 - 赵灿
 */
public class Test {
	public static void main(String[] args) {
		// 调用不同的构造方法创建子类对象
		Son son = new Son();
		//调用从父类中继承的方法
		son.work();
		//调用自己的方法
		son.play();
		son.study();
		
		System.out.println("----- 父类引用指向子类对象 -----");
		//父类引用指向子类对象
		Father f = new Son();
		//使用父类的引用指向子类的对象,可以调用父类自己的方法
		f.work();
		//调用已经被子类重写了的方法时,执行的是子类中重写后的方法
		f.play();
	}
}
运行结果:
父亲在辛苦的工作
儿子还小,只能跟着父亲玩
儿子在学习
----- 父类引用指向子类对象 -----
父亲在辛苦的工作
儿子还小,只能跟着父亲玩
由结果可以看到,子类对象赋值给子类引用(子类变量)时,子类引用可以调用父类中除private修饰以外的成员。当子类对象赋值给父类引用(父类变量:此时存在自动类型转换,即子类型转换成父类型),此时父类引用无法使用任何子类中的属性和子类中独有的其他方法,调用被子类重写的方法时,执行的是子类中重写后的方法


总结:1、继承的优点:有效的复用代码,很好的解决了代码冗余(重复的代码)的问题。
2、java只支持单根继承;即只能继承一个类。
3、创建子类对象时,先执行父类的构造方法,再执行子类的构造方法。默认执行父类的无参构造
4、使用super关键字调用父类的构造方法时,必须写在子类构造方法中的第一行。
5、使用关键字super可以访问父类中访问修饰符允许访问的成员
6、如果子类中的属性和父类中的属性没有重名,也可以使用this或省略this的方式访问父类中的属性
7、子类引用指向子类对象时,子类引用可以调用自身访问修饰符允许访问的成员,和从父类继承的成员。
8、父类引用指向子类对象时,父类引用可以调用自身访问修饰符允许访问的成员,和子类中重写父类的方法,但无法调用子类中独有的方法
9、只有方法存在重写,属性不存在重写