2021-07-06继承

继承

1.继承是从已有类中,派生出新的类,新的类拥有父类的属性和行为,并且还能扩展新的属性和行为

2.Java中只支持单继承,不支持多继承,这样可以让Java中的继承关系比较简单

一个类只能有一个父类,但是一个父类可以有很多子类,易于维护和管理

为了解决单继承功能变弱问题,Java提出了接口,一个类可以实现多个接口

3.继承是可以传递的,比如A继承B,B继承C ,则A也会拥有C的功能

4.私有属性和构造方法是不能被继承

5.如果一个类没有显示继承其他类,则该类提供Object

Java.lang.Object是Java提供的根类(祖宗)

Object中的功能,是所有类对象都有的

解决的问题

提高了代码的效率,避免了代码的重写,提高代码重用性

语法

[修饰符] class  子类名 extends  父类名{ }

public class Extends_01 {
	public static void main(String[] args) {
			Sub sub = new Sub();
			sub.m1();
			sub.m2();
	}
}
class Sup{
	public void m1(){
		System.out.println("父类的m1方法");
	}
}
class Sub extends Sup{
	public void m2(){
		System.out.println("子类的m2方法");
	}
}

super

1 官方说法是保存了父类型特征

  2 在有继承关系的体系中,可以通过super表示父类的数据

能做什么

1 用在成员/构造方法中,区分父类和子类同名的数据(同名后,子类优先级高,想使用父类,就需要使用super.xxx才行)
 *         2 用在子类构造方法中,调用指定的父类构造方法
 *                 语法 : super(参数) ; 必须在子类构造方法第一行
 *                 如果子类构造方法中 没有使用 this(xxx)  也没有使用 super(xxx) 则有一个 super() 去调用父类的无参构造
 *                 this(xxx) 和 super(xxx) 都必须出现在构造方法第一行,也就意味着 它们两个 不能同时出现
 *         3 this和super 都不能出现在静态上下文中

用法

区分父子类同名属性

public static void main(String[] args) {
		Sub sub = new Sub();
		sub.print();
	}
}
class Sup{
	int i = 10;
}
class Sub extends Sup{
	int i = 20;
	public void print(){
		int i = 30;
		// 局部变量优先级高
		System.out.println(i);
		// this区分同名局部和成员
		System.out.println(this.i);
		// super区分父子类同名属性
		System.out.println(super.i);
	}
}

调用父类指定构造方法

public static void main(String[] args) {
		Sub_01 s = new Sub_01();
		
	}
}
class Sup_01{
	// 父类实例,父类构造,子类实例,子类构造
	{
		System.out.println("父类实例语句块");
	}
	Sup_01(int i){
		System.out.println("父类构造方法");
	}
}
class Sub_01 extends Sup_01{
	{
		System.out.println("子类实例语句块");
	}
	Sub_01(){
		// 默认就会有super() 去调用父类的无参构造
		super(2);
		System.out.println("子类构造方法");
	}
}
class Sup_02 {
	// 构造方法私有化之后,就不能再被继承了
	// 因为子类构造方法中需要调用父类构造方法,一旦私有化,就会因为权限问题访问不了
	private Sup_02() {
		super();
	}
}

override

是什么

Override 是 方法重写/覆写/覆盖  , 覆写特指成员方法,除了成员方法,其他的都不能覆写

应用场景

1 什么时候需要对父类方法进行覆写
 *                 当父类的功能满足不了子类需求的时候
 *         2 覆写条件
 *                 2.1 有继承关系的体系中
 *                 2.2 方法名必须一致,如果方法名不一致,就是两个方法了
 *                 2.3 参数列表必须一致,如果参数列表不一致,这是方法重载,也是两个方法
 *                 2.4 返回值必须一致
 *                 2.5 不能有更宽泛的异常(异常只能越来越少)
 *                 2.6 不能有更低的访问权限
 *         3 覆写的意义
 *                 功能越来越强
 *                 使用范围越来越广
 *                 错误越来越少
 *                 

public static void main(String[] args) {
		Cat cat = new Cat();
		cat.move();
	}
}
class Animal{
	public void move(){
		System.out.println("动物在移动");
	}
}
class Cat extends Animal{
	// @Override是源码注解,在编译的时候,判断该方法是否是覆写的方法,防止写错,仅此而已,生成class之后该注解就会被去掉
	// 如果不加,比如方法名写错了,那么最多也就是两个方法,不会报错,但是加上@Override就会进行校验操作
	@Override
	// 父类满足不了子类的需求 需要进行重写
	public void move() {
		System.out.println("猫在跳");
	}
}

final

是什么

 final : 是修饰符,表示最后的,最终的,不可更改的 
 * 
 * 类 : final修饰的类 不能被继承 
 * 
 * 变量 : 没有默认值,不能二次赋值,必须显式赋值(不能有不赋值的情况) 
 * 
 * 方法 : final修饰的成员方法不能被覆写
 * 
 * final 修饰的静态变量,一般称为常量 , public static final xxxx;  常量名建议全部大写

怎么用

public class Final_01 {
	// final修饰 没有默认值
	final int age;
	public static final String NAME = "xx";
	Final_01() {
		// 不能二次赋值
		// age = 1;
		age = 2;
	}

	public static void main(String[] args) {

	}
}
final class A{
	
}
// 不能从最终A 进行继承
//class B extends A{
//}
class B {
	public final void m1(){
		
	}
}

class C extends B {
	// final修饰的成员方法不能被覆写
	// @Override
	// public void m1() {
	// }
}
public static void main(String[] args) {
		final int age = 1;
		// 不能二次赋值
		// age = 2;

		// final修饰的user
		final User user = new User(10);
		// 而age并没有加final修饰,我们也并没有更改user的值,所以可以更改age
		user.age = 13;
		System.out.println(user.age);
		// 但是不能再次更改user的值
		// user = null;
	}
}

class User {
	int age;

	public User(int age) {
		super();
		this.age = age;
	}

多态

什么是多态

多态就是里氏替换原则的一种体现
 *                 能使用父类的地方就一定可以使用子类
 * 
 *         多态 就是 父类引用指向子类对象
 *             父类引用 : 使用父类类型 创建的引用类型变量
 *             指向 : 通过这个引用可以找到谁
 *             通过父类创建的一个引用类型变量,找到了子类的对象
 *             父类类型  变量名 =  new 子类();
 *             Animal a = new Animal();
 *             Animal a = new Cat() ; 多态
 * 
 *         有变量的地方,就能发生多态,并且多态发生在赋值的时候
 * 
 *         多态的缺点 : 丢失子类特有的属性

多态的几种形式

1 直接多态 : 父类  变量 = new 子类();
 *         2 形参/实参 : 参数列表用父类声明, 调用方法 传递子类对象
 *                 public void m1(Animal a){}
 *                 m1(new Cat());
 *         3 返回值多态 : 返回值类型是父类类型,但是返回的对象 是子类对象
 *                 public  Animal m2(){
 *                     return new Cat();
 *                 }
 *                 Animal a = m2();

多态进行属性调用

1 父类没有的,都调用不了(因为多态缺点,丢失子类特有的属性)
 *         2 父类有的,子类没有的,执行父类
 *         3 父类和子类都有,除了成员方法执行子类,其他全部执行父类(因为只有成员方法可以覆写)

public static void main(String[] args) {
		// 直接多态
		Animal a = new Cat();
		
		
		// 返回值多态
		Animal i = m1();
		
		// 形参实参多态
		m2(new Cat());
	}
	public static void m2(Animal a ){
	}
	public static Animal m1(){
		return new Cat();
	}
	
}
class Animal{
	
}
class Cat extends Animal{
	
}
class Dog extends Animal{
	
}

例子

public class Poly_02 {
	public static void main(String[] args) {
		Dog_1 d = new Dog_1();

		test(d);

		Cat_1 c = new Cat_1();
		test(c);
	}

	// 需求 : 编写方法,要求能够接收所有的对象,并调用该对象的move方法
	// 如果后续想接收其他动物,就需要改动源码,扩展性不强
	// public static void test(Cat_1 cat) {
	// cat.move();
	// }
	//
	// public static void test(Dog_1 dog) {
	// dog.move();
	// }
	
	// 多态形式,只要传递的对象是Animal_1的子类都是可以的
	// 所以后续想接收其他动物,这里也不需要改动,更能拥抱变化
	 public static void test(Animal_1 animal_1) {
		 animal_1.move();
	 }
}

class Animal_1 {
	public void move() {
	}
}

class Cat_1 extends Animal_1 {
	public void move() {
		System.out.println("猫走猫步");
	}
}

class Dog_1 extends Animal_1 {
	public void move() {
		System.out.println("狗蹦蹦跳跳");
	}
}

上一篇:学习笔记—前端基础之构造函数与类


下一篇:java笔记