文章目录
- 前言
- 一、继承的概念
- 二、继承的步骤
- 1.类的继承格式
- 2.继承的实例
- 3.继承类型
- 三、继承的特性
- 四、继承的关键字
- 1.extends关键字
- 2.implements关键字
- 3.super 与 this 关键字
- 4.final 关键字
- 五、构造器
前言
一、继承的概念
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
兔子和羊属于食草动物类,狮子和豹属于食肉动物类。
食草动物和食肉动物又是属于动物类。
所以继承需要符合的关系是:is-a,父类更通用,子类更具体。
虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。
二、继承的步骤
1.类的继承格式
在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:
class 父类 {
}
class 子类 extends 父类 {
}
2.继承的实例
接下来我们通过实例来说明这个需求。
开发 People 类,其中有 Student 类和 Teacher 类。
- 学生 Student,属性(名字 name,年龄 age,成绩 grades),方法(自我介绍 talk,学习 study)
- 老师 Teacher,属性(名字 name,年龄 age,月薪 salary),方法(自我介绍 talk,教学 teach)
在 Student 类和 Teacher 类当中,有一些属性和方法是共有的,可以提炼成父类 People,减少代码重复。
- 父类 People,属性(名字 name,年龄 age),方法(自我介绍 talk)
父类People:
package com.zh.d7_extends;
/**
* @ClassName: People
* @Description: 父类People
* @author: Zh
* @date: 2024/4/20 9:09
*/
public class People {
private String name; // 名字
private int age; // 年龄
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 void talk() {
System.out.println("大家好,我的名字是" + getName() + "," + getAge() + "岁");
}
}
子类Student:
package com.zh.d7_extends;
/**
* @ClassName: Student
* @Description: 子类Student继承父类People
* @author: Zh
* @date: 2024/4/20 9:09
*/
public class Student extends People {
private double grades; // 成绩
public double getGrades() {
return grades;
}
public void setGrades(double grades) {
this.grades = grades;
}
/**
* Student类,独有的行为
*/
public void study() {
System.out.println(getName() + "学生开始学习~~~~");
}
}
子类Teacher:
package com.zh.d7_extends;
/**
* @ClassName: Teacher
* @Description: 子类Teacher继承父类People
* @author: Zh
* @date: 2024/4/20 9:10
*/
public class Teacher extends People {
private double salary; // 月薪
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
/**
* Teacher类,独有的行为
*/
public void teach() {
System.out.println(getName() + "老师在教Java~~~~");
}
}
测试,看子类继承父类以后,进行调用:
package com.zh.d7_extends;
/**
* @ClassName: ExtendsTest
* @Description: 继承(面向对象的三大特征:封装、继承、多态)
* @author: Zh
* @date: 2024/4/20 8:49
*/
public class ExtendsTest {
public static void main(String[] args) {
// 创建子类对象,看是否可以使用父类的属性和行为
System.out.println("----学生----");
Student s = new Student();
s.setName("西门吹雪"); // 父类People的属性
s.setAge(25); // 父类People的属性
s.setGrades(87.5); // 子类Student的属性
System.out.println("名字:" + s.getName());// 父类People的属性
System.out.println("年龄:" + s.getAge());// 父类People的属性
System.out.println("分数:" + s.getGrades()); // 子类Student的属性
s.talk(); // 父类People的方法
s.study(); // 子类Student的方法
System.out.println("----教师----");
Teacher t = new Teacher();
t.setName("贝吉塔");
t.setAge(55);
t.setSalary(7856.34);
System.out.println("名字:" + t.getName());
System.out.println("年龄:" + t.getAge());
System.out.println("月薪:" + t.getSalary());
t.talk();
t.teach();
}
}
编译运行结果如下:
----学生----
名字:西门吹雪
年龄:25
分数:87.5
大家好,我的名字是西门吹雪,25岁
西门吹雪学生开始学习~~~~
----教师----
名字:贝吉塔
年龄:55
月薪:7856.34
大家好,我的名字是贝吉塔,55岁
贝吉塔老师在教Java~~~~
3.继承类型
需要注意的是 Java 不支持多继承,但支持多重继承。
单继承:一个人可以有爸爸。
多重继承:一个人可以有爸爸,也可以有爷爷。
不同类继承同一个类:一个人可以有孩子1和孩子2.
多继承(不支持):一个人不可以有两个爸爸。
三、继承的特性
- 子类拥有父类非 private 的属性、方法。
- 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
- 子类可以用自己的方式实现父类的方法。
- Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
- 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
四、继承的关键字
继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承 Object(这个类在 java.lang 包中,所以不需要 import)祖先类。
1.extends关键字
在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。
父类 Animal:
package com.zh.d8_extends_test;
/**
* @ClassName: Animal
* @Description: 父类Animal
* @author: Zh
* @date: 2024/4/20 9:58
*/
public class Animal {
private String name;
private int id;
public Animal(String myName, int myid) {
//初始化属性值
}
public void eat() { //吃东西方法的具体实现
}
public void sleep() { //睡觉方法的具体实现
}
}
子类 Cat,使用 extends 关键字进行继承:
package com.zh.d8_extends_test;
/**
* @ClassName: Cat
* @Description: extends关键字
* 类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。
* 子类Cat继承父类Animal
* @author: Zh
* @date: 2024/4/20 9:59
*/
public class Cat extends Animal{
public Cat(String myName, int myid) {
super(myName, myid);
}
}
2.implements关键字
使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。
接口A:
package com.zh.d8_extends_test;
/**
* @ClassName: IntfA
* @Description: 接口A
* @author: Zh
* @date: 2024/4/20 10:07
*/
public interface IntfA {
public void eat();
public void sleep();
}
接口B:
package com.zh.d8_extends_test;
/**
* @ClassName: IntfB
* @Description: 接口B
* @author: Zh
* @date: 2024/4/20 10:07
*/
public interface IntfB {
public void show();
}
类 C 用 implements 关键字继承接口 A 和接口 B:
package com.zh.d8_extends_test;
/**
* @ClassName: ClassC
* @Description: implements关键字
* 可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,
* 可以同时继承多个接口(接口跟接口之间采用逗号分隔)。
* @author: Zh
* @date: 2024/4/20 10:06
*/
public class ClassC implements IntfA,IntfB{
@Override // 接口A的方法
public void eat() {
}
@Override // 接口A的方法
public void sleep() {
}
@Override // 接口B的方法
public void show() {
}
}
3.super 与 this 关键字
- super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
- this关键字:指向自己的引用。
父类:
/**
* @ClassName: Animal
* @Description: super关键字、this关键字
* 父类Animal
* @author: Zh
* @date: 2024/4/20 10:22
*/
public class Animal {
void eat() {
System.out.println("animal : eat");
}
}
子类:
/**
* @ClassName: Dog
* @Description: super关键字、this关键字
* 子类Dog,继承父类Animal
* @author: Zh
* @date: 2024/4/20 10:22
*/
public class Dog extends Animal{
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
System.out.println("----this----");
this.eat(); // this 调用自己的方法
System.out.println("----super----");
super.eat(); // super 调用父类方法
}
}
测试类:
/**
* @ClassName: TestDemo
* @Description: super关键字、this关键字
* 测试类TestDemo
* @author: Zh
* @date: 2024/4/20 10:23
*/
public class TestDemo {
public static void main(String[] args) {
Animal a = new Animal();
a.eat(); // 父类方法
System.out.println("----super关键字、this关键字----");
Dog d = new Dog();
d.eatTest(); // 子类方法
}
}
编译运行结果如下:
animal : eat
----super关键字、this关键字----
----this----
dog : eat
----super----
animal : eat
4.final 关键字
final 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。
final 含义为 “最终的”。
使用 final 关键字声明类,就是把类定义定义为最终类,不能被继承,或者用于修饰方法,该方法不能被子类重写:
- 声明类:
final class 类名 {//类体}
- 声明方法:
修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}
注意: final 定义的类,其中的属性、方法不是 final 的。
五、构造器
子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super
关键字调用父类的构造器并配以适当的参数列表。
如果父类构造器没有参数,则在子类的构造器中不需要使用 super
关键字调用父类构造器,系统会自动调用父类的无参构造器。
父类:
public class Animal {
private String name; // 父类属性name
Animal() {
System.out.println("父类无参构造器Animal");
}
Animal(String name) {
System.out.println("父类有参构造器Animal(String name)");
this.name = name;
}
}
子类1:
public class Dog extends Animal {
private String name; // 子类属性name,和父类的name同名了
Dog() { // 自动调用父类的无参数构造器
System.out.println("子类无参构造器Dog");
}
public Dog(String name) {
super("贝吉塔"); // 调用父类中带有参数的构造器
System.out.println("子类有参构造器Dog(String name):" + name);
this.name = name;
}
}
子类2:
public class Cat extends Animal {
private String name; // 子类属性name,和父类的name同名了
Cat() {
super("卡卡罗特"); // // 调用父类中带有参数的构造器
System.out.println("子类无参构造器Cat");
}
public Cat(String name) { // 自动调用父类的无参数构造器
System.out.println("子类有参构造器Cat(String name):" + name);
this.name = name;
}
}
测试类:
public class TestDemo {
public static void main(String[] args) {
System.out.println("------Dog类继承------");
Dog sc1 = new Dog();
Dog sc2 = new Dog("布尔玛");
System.out.println("------Cat类继承------");
Cat sc3 = new Cat();
Cat sc4 = new Cat("魔人布欧");
}
}
编译运行结果如下:
------Dog类继承------
父类无参构造器Animal
子类无参构造器Dog
父类有参构造器Animal(String name)
子类有参构造器Dog(String name):布尔玛
------Cat类继承------
父类有参构造器Animal(String name)
子类无参构造器Cat
父类无参构造器Animal
子类有参构造器Cat(String name):魔人布欧