学习Java第十三天--面向对象三大特性之继承

8.2 继承

8.2.1 生活中的继承

  • 生活中的“继承”是施方的一种赠与,受方的一中获得;
  • 将一方所拥有的东西给予另一方;

8.2.2 程序中的继承

  • 程序中的继承,是类与类之间特征和行为的一种赠与或获得;
  • 两个类之间的继承关系,必须满足“is a”的关系;

8.2.3 父类的选择

  • 现实生活中,很多类别之间都存在着继承关系,都满足“is a”的关系;
  • 狗是一种动物,狗是一种生物,狗是一种物质;
  • 多个类别都可作为“狗”的父类,需要从中选择出最合适的父类;
    在这里插入图片描述
  • 功能越精细,重合点越多,越接近直接父类;
  • 功能越粗略,重合点越少,越接近Object类;(万物皆对象的概念)

8.2.4 父类的抽取

  • 可根据程序需要使用到多个具体类,进行共性抽取,进而定义父类;
    在这里插入图片描述

8.2.5 继承

  • 语法:
    class 子类 extends 父类{} //定义子类时,显示继承父类
  • 应用:
    产生继承关系之后,子类可以使用父类中的属性和方法,也可定义子类独有的属性和方法;
  • 好处:
    既提高代码的复用性,又提高代码的可扩展性;
public class TestExtends {

	public static void main(String[] args) {
		Dog dog = new Dog();
		
		dog.breed = "哈士奇";//继承自父类
		dog.age = 3;//继承自父类
		dog.sex = "公";//继承自父类
		dog.furColor = "黑白";//子类独有
		
		dog.eat();//继承自父类
		dog.run();//子类独有

	}

}

//父类
class Animal{
	String breed;//品种
	int age;//年龄
	String sex;//性别
	
	public void eat() {}
	public void sleep() {}
}
class Dog extends Animal{//完成继承父类
	String furColor;//毛色
	
	public void run() {}
}
public class TestExpents2 {

	public static void main(String[] args) {
		Car car = new Car();
		car.type = "小汽车";
		car.price = 1000000D;
		car.speed = 120;
		car.brand = "保时捷";
		car.run();

		Bus bus = new Bus();
		bus.type = "公交车";
		bus.price = 1500000D;
		bus.speed = 60;
		bus.seatNum = 20;
		bus.run();
	}

}
//交通工具类
class Vehicle{
	String type;//类型
	double price;//价格
	int speed;//速度
	
	public void run() {
		System.out.println("一辆"+this.type+"以"+this.speed+"/h的速度行驶中。。。");
	}
}

class Car extends Vehicle{
	String brand;//品牌
}

class Bus extends Vehicle{
	int seatNum;//座位数
}

8.2.6 继承的特点

在这里插入图片描述

  • Java为单继承,一个类只能有一个父类,但可以多级继承,属性和方法逐级叠加;

8.2.7 不可继承

  • 构造方法:
    类中的构造方法,只负责创建本类对象,不可继承;
  • private修饰的属性和方法:
    访问修饰符的一种,仅本类可见;
  • 父子类不再同一个package中时,default修饰的属性和方法:
    访问修饰符的一种,仅同包可见;

8.2.8 访问修饰符

- 本类 同包 非同包子类 其他
private × × ×
default × ×
protected ×
public

8.3 方法的覆盖

8.3.1 为什么要方法的覆盖

  • 思考:子类是否可以定义和父类相同的方法?
  • 思考:为什么需要在子类中定义和父类相同的方法?
  • 分析:当父类提供的方法无法满足子类需求时,可在子类中定义和父类相同的方法进行覆盖;

8.3.2 方法的覆盖的特点

  • 方法覆盖原则:
    方法名称、参数列表、返回值类型必须与父类相同;
    访问修饰符可与父类相同或是比父类更宽泛;

  • 方法覆盖的执行:
    子类覆盖父类方法后,调用时优先执行子类覆盖后的方法;

public class TestOverride {

	public static void main(String[] args) {
		Dog2 dog = new Dog2();
		
		dog.eat();//狗在吃骨头
		
		Cat cat = new Cat();
		
		cat.eat();//动物在吃

	}

}

class Animal2{
	String breed;//品种
	int age;
	String sex;
	
	public void eat() {
		System.out.println("动物在吃");
	}

	public void sleep() {
		System.out.println("动物在睡");
	}
}

class Dog2 extends Animal2{
	String furColor;//毛色
	
	//子类中定义和父类相同的方法进行覆盖
	public void eat() {
		System.out.println("狗在吃骨头");
	}
	public void run() {
		
	}
}

class Cat extends Animal2{
	
}

8.3.3 super关键字

  • 在子类中,可直接访问从父类继承到的属性和方法,但如果父子类的属性或方法存在重名(属性遮蔽、方法覆盖)时、需要加以区分,才可专项访问;
public class TestSuperKeyword {

	public static void main(String[] args) {
		B b = new B();
		b.upload();
		
		b.print();

	}

}
class A{
	int value = 10;
	
	public void upload(){
		System.out.println("父类代码");
		//上传文件的100行代码
	}
}
						
class B extends A{
	int value = 20;//父子类的同名属性不存在覆盖关系,两块空间同时存在(子类遮蔽父类属性),需使用不同前缀进行访问
	
	public void upload() {	//super关键字可在子类访问父类的方法
		super.upload();//上传文件的100行代码
		System.out.println("子类添加的代码");
		//修改文件名称的一行代码
	}						//使用“super.”的形式访问父类的方法,进而完成在子类中的复用
							//再叠加额外的功能代码,组成新的功能
	
	public void print() {
		int value = 30;
		System.out.println(value);//方法内的value
		System.out.println(this.value);//子类属性的value
		System.out.println(super.value);//父类属性的value
	}
}

8.3.6 继承中的对象的创建

  • 在具有继承关系的对象创建中,构建子类对象会先构建父类对象;
  • 由父类的共性内容,叠加子类的独有内容,组合成完整的子类对象;
class Father{
	int a;
	int b;
	public void m1(){}
}
class Son extends Father{//子类持有的属性和 方法:int a 、int b、int c、m1()、m2()
	int c;
	public void m1(){}
}

8.3.7 继承后的对象构建过程

在这里插入图片描述

8.3.8 super调用父类的构造方法

public class TestSuperKeyword2 {

	public static void main(String[] args) {
		new C();
		
		new B1();
		new B1(10);

	}

}

class A1{
	public A1() {
		System.out.println("A()");
	}
	public A1(int vlaue) {
		System.out.println("A(int value)");
	}
}
class B1 extends A1{
	public B1() {
		super();//super():表示调用父类无参的构造方法。如果没有书写,隐式存在于子类构造方法的首行
		System.out.println("B()");
	}
	public B1(int value) {
		super(value);//super(实参):表示调用父类有参的构造方法
		System.out.println("B(int value)");
	}
}
class C extends B1{
	public C() {
		super();//super():表示调用父类无参的构造方法
		System.out.println("C()");
	}
}

8.3.9 this和super

public class TestSuperKeyword3 {

	public static void main(String[] args) {
		new B2(10);
	}

}

class A2{
	public A2() {
		System.out.println("A-无参构造");
	}
	public A2(int value) {
		System.out.println("A-有参构造");
	}
}

class B2 extends A2{
	public B2() {
		super();
		System.out.println("B-无参构造");
	}
	public B2(int value) {
		this();//super();
		System.out.println("B-有参构造");
	}
}
  • this或super使用在构造方法中时,都要求在首行
  • 当子类构造中使用了this()或this(实参),即不可再同时书写super()或super(实参),会由this()执行的构造方法完成super()的调用;

8.3.10 总结

  • super关键字的第一种用法:
    在子类的方法中使用“super.”的形式访问父类的书写和方法;
    例如:super.父类书写、super.父类方法();

  • super关键字的第二种用法:
    在子类的构造方法的首行,使用“super()”或“super(实参)”,调用父类构造方法。

  • 注意:
    如果子类构造方法中,没有显示定义super()或super(实参),则默认提供super();
    同一个子类构造方法中,super()、this()不可同时存在。

发布了34 篇原创文章 · 获赞 7 · 访问量 1303

猜你喜欢

转载自blog.csdn.net/weixin_44257082/article/details/104398973