当前位置:   article > 正文

类的继承(extends)与重写(Override)_base类要求子类必须override

base类要求子类必须override

面向对象的三大特征:封装、继承、多态

一、继承

使用***extends***作为继承的关键字,如同于:扩展
——子类继承(扩展)了父类,只能获得父类的成员变量、方法和内部类,不能获得构造器和初始化块。

Java子类到父类的继承是一种由一般到特殊的关系,父类包含的范围比子类要大,
————子类=小类,父类=大类
eg: 老虎类继承动物类,苹果类继承水果类

格式即:
public class 子类 extends 父类
{
var 对象 = new 子类();
}

【]注】Java是单继承的,只能有一个直接父类
如果你不显式地继承父类,Java默认是继承Object类(是一种JDK系统提供的类)——一切都是Object的子类(直接或间接)——一切都是对象
继承的好处:代码的复用

(1)、创建父类:

public class  Fruit
{
	public double weight;
	public void info()
	{
		System.out.println("水果,重:" + weight+"g");
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

(2)、定义子类

public class  Pear extends Fruit
//创建了Pear这个子类(空的),继承了Fruit父类,可以获得父类的各种特性,成员变量、方法等。
{
	public static void main(String[] args) 
	{
		var a = new Pear();//创建Pear类的对象(实例),赋给变量a后,可以通过访问它来访问父类
		a.weight = 100;
		a.info();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

或者把继承:public class Pear extends Fruit{ }单独写
再写public class PearTest{ Pear p = new Pear();}

二、方法重写(Override)

规则:
(1)2同:子类的方法重写,其方法名要相同,形参列表要相同;
(2)2小:返回值类型要相同或者更小,声明抛出的异常要相同或更小;
(3)1大:访问权限相同或更大。

eg1:
定义父类及其方法:

public class  Brid
{
	public  void fly()
	{
		System.out.println("鸟会飞");
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

定义子类时重写其方法:

public class Ostrich extends Brid
{
	//重写fly方法
	@Override//用于报错
	public void fly()
	{
		System.out.println("鸵鸟不会飞");
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

测试:

public class  OstrichTest
{
	public static void main(String[] args) 
	{
		Ostrich os = new Ostrich();
		os.fly();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述
加上@Override是为了在重写时如果子类方法名与父类不一致,编译时会提示这个错误,否则会视为一个新的方法。

eg2:
验证:返回值类型要相同或者更小

import java.util.*;
class  Base
{
	//返回值是类
	public Object info()     //Object是所有类的父类,所以最大
	{
		System.out.println("父类的info");
		return new Random();
	}
}
public class 方法重写 extends Base
{
	@Override
	public String info()   //String比Object小,修饰符不能用protected
	{
		System.out.println("子类的info");
		return "Java";
	}
	public static void main(String[] args) 
	{
		var a = new 方法重写();//new 构造器
		a.info();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

【重申】创建对象:new 构造器(参数),由于在定义类的时候没有定义构造器,所以构造器是系统自动提供 的,所以无参数,执行体为空

典型例子

父类引用指向子类对象时:B b = new C();

1、若子类覆盖了某方法,则父类引用调用子类重新定义的新方法
2、若子类未覆盖某方法,则父类引用调用父类本身的旧方法
3、若子类覆盖了某属性,但父类引用仍调用父类本身的旧属性
4、若子类未覆盖某属性,则父类引用调用父类本身的旧属性
5、父类引用不能访问子类新定义的方法

子类引用指向自身对象时:C c = new C();

1、若子类覆盖了某方法,则子类引用调用子类重新定义的新方法
2、若子类未覆盖某方法,则子类引用调用父类本身的旧方法
3、若子类覆盖了某属性,则子类引用调用子类重新定义的新属性
4、若子类未覆盖某属性,则子类引用调用父类本身的旧属性
5、子类引用可以访问子类新定义的方法
*/

class B {
	int a = 1;
	int b = 2;
 
	void f1() {
		System.out.println("B.f1()");
	}
 
	void f2() {
		System.out.println("B.f2()");
	}
 
}

public class C extends B {
 
	int a = 3;
	@Override
	void f1() {
		System.out.println("C.f1()");
	}
 
	void f3() {
		System.out.println("C.f3()");
	}
 
	public static void main(String[] args) {
 
		B b = new C();// 父类引用指向子类对象
		b.f1();// C.f1() 子类覆盖了该方法,所以父类引用调用新方法
		b.f2();// B.f2() 子类未覆盖该方法,所以父类引用调用旧方法
		// b.f3();//此行去掉注释会报错,父类引用不能访问子类新定义方法

		System.out.println(b.a);// 1  子类覆盖了该属性,但父类引用仍旧访问旧属性
		System.out.println(b.b);// 2  子类未覆盖该属性,父类访问旧属性
 
		System.out.println();
 
		C c = new C();// 子类引用指向自身对象
		c.f1();// C.f1()
		c.f2();// B.f2()
		c.f3();// C.f3() 子类调用自己新定义的方法
		System.out.println(c.a);// 3 子类覆盖了该属性,所以访问新属性
		System.out.println(c.b);// 2 子类未覆盖该属性,所以访问旧属性
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/78771
推荐阅读
相关标签
  

闽ICP备14008679号