【Java入门】继承、抽象、方法覆盖

本文探讨Java中的继承概念,包括语法、子类继承父类成员、方法覆盖、super关键字、抽象方法与抽象类。通过实例讲解如何重写方法和使用抽象类设计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


学习目标

  • 理解继承的作用
  • 必须掌握继承的语法
  • 了解子类可以继承父类那些成员
  • 掌握方法覆盖的判断规则和如何覆盖方法
  • 掌握super关键字的含义
  • 掌握抽象方法的定义和特点
  • 掌握抽象类的定义和特点

继承思想

1、继承语法

在java程序中,如果一个类需要继承另一个类,此时使用extends关键字。

public class 父类名{
    // 存放多个子类共同的字段和方法
}

public class 子类名 extends 父类名{
    // 存放自己特有的(独有的)字段和方法
}

注意:Java中类只支持单继承,但是支持多重继承。也就是说一个子类只能有一个直接的父类,父类也可以再有父类。

  • 下面是错误的写法! Java中的类只支持单继承。
class SuperClass1 { }
class SuperClass2 { }

// 错误用法 
class SubClass extends SuperClass1,SuperClass2{
    
} 
  • 下面代码是正确的。一个父类可以有多个子类。
class SuperClass{}
class SubClass1 extends SuperClass{ }
class SubClass2 extends SuperClass{ }
  • 下面代码是正确的,支持多重继承。
class SuperSuperClass{}
class SuperClass extends SuperSuperClass{}
class SubClass extends SuperClass

例如:大学生 extends 学生,学生 extends 人类,我们就说,大学生具有人类的特征和行为。

(Object类是Java语言的根类,任何类都是Object的子类,要么是直接子类,要么是间接子类)

public class  Person {
    
} 	
等价于 	
public class Person extends Object{
    
}

1.1、继承操作

父类代码

public class Person {
	private String name;
	private int age;

	public void rest() {
		System.out.println("休息");
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

子类代码:

public class Student extends Person{
	private String sn;	// 学号
	
    public void study() {
		System.out.println("学习");
	}
    
	public String getSn() {
		return sn;
	}
    
	public void setSn(String sn) {
		this.sn = sn;
	} 
}

测试代码:

public class ExtendsDemo {
	public static void main(String[] args) {
		// 创建学生对象
		Student stu = new Student();
		// 设置字段信息
		stu.setName("will");	//继承了父类
		stu.setAge(17);			//继承了父类
		stu.setSn("s_123");
		// 调用方法
		stu.study();
		stu.rest();				//继承了父类
	}
}

1.2、子类可以继承到父类的哪些成员

子类继承父类之后,可以拥有到父类的某一些成员(字段和方法),根据访问修饰符来判断:

  • 如果父类中的成员使用public和protected修饰,子类都能继承.
  • 如果父类和子类在同一个包中,使用缺省访问修饰的成员,此时子类可以继承到
  • 如果父类中的成员使用private修饰,子类继承不到。private只能在本类中访问
  • 父类的构造器,子类也不能继承,因为构造器必须和当前的类名相同

在这里插入图片描述

private: 私有的,本类可见。
默认: 同包可见,也经常把它成为包访问权限。
protected: 受保护的。1 同包可见  2 子类可见
public 公共的。任何地方可见

一句话:子类继承父类的非私有成员(字段和方法),但构造器除外。


2、方法覆盖

子类继承了父类,可以拥有父类的部分方法和成员变量。**可是当父类的某个方法不适合子类本身的特征时,此时怎么办?**比如鸵鸟(Ostrich)是鸟类(Bird)中的一个特殊品种,所以鸵鸟类是鸟类的一个子类,但是鸟类有飞翔的功能,但是对应鸵鸟,飞翔的行为显然不适合于它。

父类:

public class Bird {
	public void fly() {
		System.out.println("飞呀飞...");
	}
}

子类:

public class Ostrich extends Bird{
}

测试类:

public class OverrideDemo {
	public static void main(String[] args) {
		//创建鸵鸟对象
		Ostrich os = new Ostrich();
		//调用飞翔功能
		os.fly();
	}
}

运行结果:

飞呀飞...

上述代码从语法是正确的,但从逻辑上是不合理的,因为鸵鸟不能飞翔,此时怎么办?——方法覆盖操作。

2.1、方法覆盖的操作

当子类存在一个和父类一模一样的方法时,我们就称之为子类覆盖了父类的方法,也称之为重写(override)

提示:
当子类继承父类的方法时不能满足自身需要时,子类就可以根据自身需要对父类的同名方法进行重写。

那么我们就可以在子类方法体中,重写编写逻辑代码。

public class Ostrich extends Bird{
	public void fly() {
		System.out.println("扑扑翅膀,快速奔跑...");
	}
}

运行测试代码:

扑扑翅膀,快速奔跑...

重写方法的调用顺序

通过对象调用方法时,先在子类中查找有没有对应的方法,若存在就执行子类的,若子类不存在就执行父类的,如果父类也没有,报错。

方法覆盖的细节:(理解掌握)

  1. 实例方法签名必须相同 (方法签名= 方法名 + 方法的参数列表)
  2. 子类方法的返回值类型是和父类方法的返回类型相同或者是其子类
  3. 子类方法的访问权限 >= 父类方法访问权限

    如果父类方法是private,子类方法不能重写。==> 重写建立在继承的基础上,没有继承,就不能重写。

  4. 子类方法中声明抛出的异常小于或等于父类方法声明抛出异常类型 (后续讲解)

上述的方法覆盖细节真多,记不住,那么记住下面这句话就万事OK了。

精华:直接拷贝父类中方法的定义粘贴到子类中,再重新编写子类方法体,打完收工!

2.2、覆盖中super关键字

问题,在子类中的某一个方法中需要去调用父类中被覆盖的方法,此时得使用super关键字。

public class Ostrich extends Bird{
	public void fly() {
		System.out.println("扑扑翅膀,快速奔跑...");
	}
	
	public void say() {
		super.fly();//调用父类被覆盖的方法
		fly();//调用本类中的方法
	}
}

如果调用被覆盖的方法不使用super关键字,此时调用的是本类中的方法。

  • super关键字表示父类对象的意思

  • super.fly() 可以翻译成调用父类对象的fly方法。

3、抽象方法和抽象类

3.1、引出抽象方法

需求:求圆(Circle)和矩形(Rectangle)两种图形的面积。

分析:无论是圆形还是矩形,还是其他形状的图形,只要是图形,都有面积,也就说图形都有求面积的功能,那么我们就可以把定义一个图形(Graph)的父类,该类拥有求面积的方法,但是作为图形的概念,而并不是某种具体的图形,那么怎么求面积是不清楚的。

所以由上述需求的问题引出:

  • 既然不同的图形求面积的算法是不同的,所以必须要求每一个图形子类去覆盖getArea方法,如果没有覆盖,应该以语法报错的形式做提示。
  • 在Graph类中的getArea方法的方法体没有任何存在意义,因为不同图形求面积算法不一样,子类必须要覆盖getArea方法。

要满足上述对方法的要求,就得使用abstract来修饰方法,被abstract修饰的方法具备两个特征:

  • 该方法没有方法体

  • 要求子类必须覆盖该方法

这种方法,我们就称之为抽象方法

3.2、抽象方法和抽象类

使用abstract修饰的方法,称为抽象方法。

public abstract 返回类型 方法名(参数);

抽象方法的特点:

  • 使用abstract修饰,没有方法体,留给子类去覆盖

  • 抽象方法必须定义在抽象类或接口中

注意:

  • 如果要定义抽象方法,那么这个类就必须是抽象类
  • 抽象类中可以同时存在抽象方法和普通方法
  • 集成这个抽象类的子类必须实现抽象类中的抽象方法,或者这个子类也是一个抽象类
  • 抽象方法没有方法体,方法体需要子类去写具体的实现
  • 抽象类不能创建对象,只能继承他的子类创建对象,同时这个子类也不能是抽象类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值