Java面向对象-继承

目录

继承的概念

生活中的继承

类的继承格式

为什么要继承

继承类型

单继承

多重继承

不同类继承同一个类

不支持多继承 

继承的特性

继承的关键字

extends

implements

super和this

final

修饰变量:

修饰方法:

修饰类:

构造器

当父类的构造器带有参数

当父类构造器不带参数


继承的概念

继承就是,子类从父类继承方法,使得子类有和父类一样的行为。

生活中的继承

食草动物有自己的属性和方法,同样食肉动物也有自己的属性和方法,但两者肯定都是动物,有一定的共性,同样也保留自己的个性。更形象地讲,父类是通用的,子类是具体的。

类的继承格式

class 父类 {
}
 
class 子类 extends 父类 {
}

为什么要继承

下面是用一个例子来更好地说明有继承这个特性:

下面是两个类,企鹅和老鼠

public class Penguin { 
    private String name; 
    private int id; 
    public Penguin(String myName, int  myid) { 
        name = myName; 
        id = myid; 
    } 
    public void eat(){ 
        System.out.println(name+"正在吃"); 
    }
    public void sleep(){
        System.out.println(name+"正在睡");
    }
    public void introduction() { 
        System.out.println("大家好!我是"         + id + "号" + name + "."); 
    } 
}
public class Mouse { 
    private String name; 
    private int id; 
    public Mouse(String myName, int  myid) { 
        name = myName; 
        id = myid; 
    } 
    public void eat(){ 
        System.out.println(name+"正在吃"); 
    }
    public void sleep(){
        System.out.println(name+"正在睡");
    }
    public void introduction() { 
        System.out.println("大家好!我是"         + id + "号" + name + "."); 
    } 
}

通过阅读两段代码,不难发现,两段代码存在大量的相似代码,造成代码冗余。并且更重要的是,后期的可维护性不高,因为一旦要修改代码,就要做大量重复工作。所以,我们使用继承的特性,创建一个Animal的父类:

public class Animal { 
    private String name;  
    private int id; 
    public Animal(String myName, int myid) { 
        name = myName; 
        id = myid;
    } 
    public void eat(){ 
        System.out.println(name+"正在吃"); 
    }
    public void sleep(){
        System.out.println(name+"正在睡");
    }
    public void introduction() { 
        System.out.println("大家好!我是"         + id + "号" + name + "."); 
    } 
}

然后创建两个子类来继承这个父类,这样的两个子类就会更清晰、更简洁。并且代码的复用性很高,后期也更方便维护:

public class Penguin extends Animal { 
    public Penguin(String myName, int myid) { 
        super(myName, myid); 
    } 
}

public class Mouse extends Animal { 
    public Mouse(String myName, int myid) { 
        super(myName, myid); 
    } 
}

继承类型

  • 要注意的是,Java只支持单继承和多重继承,并不支持多继承!!!
  • 单继承

  • 多重继承

  • 不同类继承同一个类

  • 不支持多继承 

这里要理解一下多继承,是指子类继承多个父类,并不是指一个父类有多个子类。 

继承的特性

  • 继承的子类可以有父类的非private的属性、方法
  • 继承的子类可以有自己特有的属性和方法(即对父类的扩展)
  • 继承的子类可以使用自己的方式调用父类的方法
  • Java中的继承是单继承,但是支持多重继承
  • 继承会提高代码的耦合性(继承的缺点,耦合性的提高,会降低代码的独立性)

继承的关键字

  • extends

含义:当一个类使用“extends”关键字时,它表示这个类是从另一个类派生出来的,继承了父类的属性和方法。这种继承是单继承,即一个类只能有一个父类。
形象解释:可以想象成“亲子关系”。比如有一个“动物”类,它有一些基本的属性和行为,如“名字”、“年龄”、“吃东西”等。然后有一个“狗”类,它使用“extends”关键字继承了“动物”类。这就像是“狗”是“动物”的孩子,它继承了“动物”的一些基本特征和行为,同时还可以有自己的独特行为,比如“汪汪叫”。

  • implements

含义:这个关键字用于实现接口。在 Java 中,接口是一种特殊的抽象类,它只包含抽象方法和常量。当一个类使用“implements”关键字时,它表示这个类实现了某个接口,需要提供接口中所有抽象方法的具体实现。
形象解释:可以想象成“契约关系”。比如有一个“可飞”接口,它定义了一个“飞行”的方法。然后有一个“鸟”类,它使用“implements”关键字实现了“可飞”接口。这就像是“鸟”和“可飞”之间签订了一个契约,“鸟”承诺会实现“飞行”这个行为,具体怎么飞由“鸟”自己决定。

  • super和this

super:可以用来访问当前对象的父类

this:引用当前的对象

class Animal {
    void eat() {
        System.out.println("animal : eat");
    }
}
 
class Dog extends Animal {
    void eat() {
        System.out.println("dog : eat");
    }
    void eatTest() {
        this.eat();   // this 调用自己的方法
        super.eat();  // super 调用父类方法
    }
}
 
public class Test {
    public static void main(String[] args) {
        Animal a = new Animal();
        a.eat();
        Dog d = new Dog();
        d.eatTest();
    }
}

 运行结果是:

animal : eat
dog : eat
animal : eat

final

final 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。

  • 修饰变量:

final int age = 25; // 一旦赋值为25,就不能再修改
// age = 30; // 这会报错,因为age是final变量
  • 修饰方法:

class Animal {
    final void eat() {
        System.out.println("Animals eat food.");
    }
}

class Dog extends Animal {
    // 下面的代码会报错,因为eat()方法是final,不能被重写
    // @Override
    // void eat() {
    //     System.out.println("Dogs eat bones.");
    // }
}
  • 修饰类:

final class FinalClass {
    void display() {
        System.out.println("This is a final class.");
    }
}

// 下面的代码会报错,因为FinalClass是final类,不能被继承
// class SubClass extends FinalClass {
// }

final的核心思想是“不可变性”和“不可扩展性”,它在程序设计中用于确保某些关键部分的稳定性和安全性。

构造器

子类并不会继承父类的构造器,但是会调用父类的构造器。目的是,在子类被正确创建的过程中,父类也能够被正确加载。

形象解释:可以想象一个“两层建筑”:

  1. 第一层是父类,第二层是子类。

  2. 在建造第二层之前,必须先完成第一层的建造。父类的构造器负责初始化第一层,子类的构造器负责初始化第二层。

当父类的构造器带有参数

这时,子类就会需要使用super关键字显式的调用父类的构造器:

class Parent {
    int x;

    //父类构造器有参数
    Parent(int x) {
        this.x = x;
        System.out.println("Parent constructor called, x = " + x);
    }
}

class Child extends Parent {
    int y;

    Child(int x, int y) {
        super(x); // 显式调用父类的构造器
        this.y = y;
        System.out.println("Child constructor called, y = " + y);
    }
}

public class Main {
    public static void main(String[] args) {
        Child obj = new Child(10, 20);
    }
}

输出结果:

Parent constructor called, x = 10
Child constructor called, y = 20

当父类构造器不带参数

class Parent {
    int x;

    //父类构造器无参数
    Parent() {
        x = 10;
        System.out.println("Parent constructor called, x = " + x);
    }
}

class Child extends Parent {
    int y;

    Child() {
        y = 20;
        System.out.println("Child constructor called, y = " + y);
    }
}

public class Main {
    public static void main(String[] args) {
        Child obj = new Child();
    }
}

输出结果:

Parent constructor called, x = 10
Child constructor called, y = 20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值