详解java继承

目录

一 、为什么需要继承

二、准备工作:用java代码先定义狗类、猫类、动物类,这是代码准备如下

三、继承代码实现

四、 子类中访问父类的成员方法

4.1. 成员方法名字不同

4.2 成员方法名字相同

五、子类构造方法

扩展:如果你对子类和父类的代码执行的顺序搞不清楚可以参考:

六、super和this异同点

七、继承种类

八、继承和组合关系

1、概念介绍

2、优缺点对比

3、如何选择


一 、为什么需要继承

Java 中使用类对现实世界中实体来进行描述,类经过实例化之后的产物对象,则可以用来表示现实中的实体,但是现实世界错综复杂,事物之间可能会存在一些关联,那在设计程序是就需要考虑。
比如: 狗和猫,它们都是一个动物,我们可以把猫和狗归结为一个类就是动物类。

详解java继承_第1张图片

详解java继承_第2张图片

二、准备工作:用java代码先定义狗类、猫类、动物类,这是代码准备如下

   动物类

// Animal.java
public class Animal{
    String name;
    int age;
    public void eat(){
    System.out.println(name + "正在吃饭");
    }
    public void sleep(){
    System.out.println(name + "正在睡觉");
    }
}

狗类

// Dog.java
public class Dog{
    string name;
    int age;
    float weight;
    public void eat(){
    System.out.println(name + "正在吃饭");
    }
    public void sleep(){
    System.out.println(name + "正在睡觉");
    }
    void Bark(){

    System.out.println(name + "汪汪汪~~~");
    }
}

猫类

public class Cat{
    string name;
    int age;
    float weight;
    public void eat(){
    System.out.println(name + "正在吃饭");
    }
    public void sleep()
    {
    System.out.println(name + "正在睡觉");
    }
    void mew(){
    System.out.println(name + "喵喵喵~~~");
    }
}

三、继承代码实现

Java 中如果要表示类之间的继承关系,需要借助 extends 关键字,具体如下
修饰符 class 子类 extends 父类 {
// ... 
}

连接上述定义的三个类:

// Animal.java
public class Animal{
    String name;
    int age;
    public void eat(){
    System.out.println(name + "正在吃饭");
    }
    public void sleep(){
    System.out.println(name + "正在睡觉");
    }
}
// Dog.java
public class Dog extends Animal{
    void bark(){
    System.out.println(name + "汪汪汪~~~");
    }
}

// Cat.Java
public class Cat extends Animal{
    void mew(){
    System.out.println(name + "喵喵喵~~~");
    }
}
// TestExtend.java
public class TestExtend {
    public static void main(String[] args) {
    Dog dog = new Dog();
    // dog类中并没有定义任何成员变量,name和age属性肯定是从父类Animal中继承下来的
    System.out.println(dog.name);
    System.out.println(dog.age);
    // dog访问的eat()和sleep()方法也是从Animal中继承下来的
    dog.eat();
    dog.sleep();
    dog.bark();
    }
}

四、 子类中访问父类的成员方法

4.1. 成员方法名字不同

public class Base {
  public void methodA(){
  System.out.println("Base中的methodA()");
  }
}
public class Derived extends Base{
  public void methodB(){
  System.out.println("Derived中的methodB()方法");
  }
  public void methodC(){
  methodB(); // 访问子类自己的methodB()
  methodA(); // 访问父类继承的methodA()
  // methodD(); // 编译失败,在整个继承体系中没有发现方法methodD()
  }
}

4.2 成员方法名字相同

public class Base {
    public void methodA(){
    System.out.println("Base中的methodA()");
    }
    public void methodB(){
    System.out.println("Base中的methodB()");
    }
}
public class Derived extends Base{
    public void methodA(int a) {
    System.out.println("Derived中的method(int)方法");
    }
    public void methodB(){
    System.out.println("Derived中的methodB()方法");
    }
    public void methodC(){
    methodA(); // 没有传参,访问父类中的methodA()
    methodA(20); // 传递int参数,访问子类中的methodA(int)
    methodB(); // 直接访问,则永远访问到的都是子类中的methodB(),基类的无法访问到
    }
}
【上述说明】
        通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
        通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同( 重载 ) ,根据调用 方法适传递的参数选择合适的方法访问,如果没有则报错;
问题:如果子类中存在与父类中相同的成员时,那如何在子类中访问父类相同名称的成员呢?
答:可以通过在子类中定义super.方法名进行访问父类中被子类重写的方法。

五、子类构造方法

父子父子,先有父再有子,即:子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法。
public class Base {
    public Base(){
    System.out.println("Base()");
    }
    }
public class Derived extends Base{
    public Derived(){
    // super(); // 注意子类构造方法中默认会调用基类的无参构造方法:super(),
    // 用户没有写时,编译器会自动添加,而且super()必须是子类构造方法中第一条语句,
    // 并且只能出现一次
    System.out.println("Derived()");
    }
}
public class Test {
    public static void main(String[] args) {
    Derived d = new Derived();
    }
}
结果打印:
Base()
Derived()

扩展:如果你对子类和父类的代码执行的顺序搞不清楚可以参考:

执行顺序
优先级从上到下依次递减
静态代码(先执行父类静态在执行子类静态块)
父类实例代码块
父类构造代码
子类实例代码
子类构造代码

六、superthis异同点

相同点
1. 都是 Java 中的关键字
2. 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
3. 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
不同点
1. this 是当前对象的引用,当前对象即调用实例方法的对象, super 相当于是子类对象中从父类继承下来部分成
员的引用
2. 在非静态成员方法中, this 用来访问本类的方法和属性, super 用来访问父类继承下来的方法和属性
3. 在构造方法中: this(...) 用于调用本类构造方法, super(...) 用于调用父类构造方法,两种调用不能同时在构造
方法中出现
4. 构造方法中一定会存在 super(...) 的调用,用户没有写编译器也会增加,但是 this(...) 用户不写则没有

七、继承种类

详解java继承_第3张图片

注意:被final修饰的类不能被继承

八、继承和组合关系

1、概念介绍

和继承类似 , 组合也是一种表达类之间关系的方式 , 也是能够达到代码重用的效果。组合并没有涉及到特殊的语法
( 诸如 extends 这样的关键字 ), 仅仅是将一个类的实例作为另外一个类的字段。
继承表示对象之间是 is-a 的关系 ,比如:狗是动物,猫是动物
组合表示对象之间是 has-a 的关系 ,比如:汽车
// 轮胎类
class Tire{
// ...
}
// 发动机类
class Engine{
// ...
}
// 车载系统类
class VehicleSystem{
// ...
}
class Car{
private Tire tire; // 可以复用轮胎中的属性和方法
private Engine engine; // 可以复用发动机中的属性和方法
private VehicleSystem vs; // 可以复用车载系统中的属性和方法
// ...
}
// 奔驰是汽车
class Benz extend Car{
// 将汽车中包含的:轮胎、发送机、车载系统全部继承下来
}
组合和继承都可以实现代码复用,应该使用继承还是组合,需要根据应用场景来选择,一般建议:能用组合尽量用组合。

2、优缺点对比

组 合 关 系 继 承 关 系
优点:不破坏封装,整体类与局部类之间松耦合,彼此相对独立 缺点:破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性
优点:具有较好的可扩展性 缺点:支持扩展,但是往往以增加系统结构的复杂度为代价
优点:支持动态组合。在运行时,整体对象可以选择不同类型的局部对象 缺点:不支持动态继承。在运行时,子类无法选择不同的父类
优点:整体类可以对局部类进行包装,封装局部类的接口,提供新的接口 缺点:子类不能改变父类的接口
缺点:整体类不能自动获得和局部类同样的接口 优点:子类能自动继承父类的接口
缺点:创建整体类的对象时,需要创建所有局部类的对象 优点:创建子类的对象时,无须创建父类的对象

3、如何选择

相信很多人都知道面向对象中有一个比较重要的原则『多用组合、少用继承』或者说『组合优于继承。从前面的介绍已经优缺点对比中也可以看出,组合确实比继承更加灵活,也更有助于代码维护。并不是说继承就一点用都没有了,前面说的是【在同样可行的情况下】。有一些场景还是需要使用继承的,或者是更适合使用继承。

你可能感兴趣的:(java,开发语言)