美文网首页
java基础之组合和继承

java基础之组合和继承

作者: 墨线宝 | 来源:发表于2023-10-07 10:29 被阅读0次

为了避免重复代码太多,导致代码不好维护,大家需要学会如何复用代码,代码复用的两种方式,组合和继承

组合:在新类中创建现有类的对象 has-a
继承:创建现有类的新类 is-a
依赖:uses-a

UML关系

继承

继承使用的关键字是extends,Object是所有类的父类,在Java中每个类都是由Object扩展来的,如果没有明确地指出父类,Object就被认为是这个类的父类

继承中的构造方法调用

子类在自己的构造方法调用父类构造方法时可以使用super(参数列表)来调用,注意在调用时要写在构造方法的第一行

super的作用

  • 调用父类的方法
  • 调用父类的构造器

多态

存在多态的必要条件

  • 继承
  • 方法重写
  • 父类引用指向子类对象

向上转型

class Instrument {
    public void play() {
        System.out.println("Instrument.play()");
    } 
}

public class Wind extends Instrument {
    public void play() {
        System.out.println("Wind.play()");
    }
}

public class Music {
    
    public static void tune(Instrument i){
        i.play();
    }
    public static void main(String[] args) {
        Wind flute = new Wind();
        Music.tune(flute); // 向上转型
    }
}

从一个更具体的类型转化为更一般的类型,所以向上转型用法是安全的。子类可能会比父类包含更多的方法,必须至少具有和父类一样的方法。

instanceof

可以在进行类型转换时使用instanceof来判断该对象是否属于该类或者该类的子类,以此来进行强转,调用该类所特有的方法

// 获取父类的泛型
if(superType instanceof ParameterizedType){ // 如果存在泛型
    Type[] actualTypeArguments = ((ParameterizedType) superType).getActualTypeArguments();
}

方法绑定

对于上述向上转型的例子,编译器如何知道该调用哪个方法,方法的入参只是一个Instrument引用?
java采用后期绑定,在运行时根据对象的类型进行绑定,在运行时判断对象的类型,从而调用方法,在编译时编译器不知道对象的类型,java对于static和final方法无法采用后期绑定(private方法也是隐式的final)

调用的过程
  • 编译器查看对象的声明类型和方法,此时会一一列举出该类以及父类中名称为方法名的方法(父类的私有方法不可访问)
  • 编译器查看调用方法时提供的参数类型
  • 如果是private方法、static方法、final方法或者构造器,那么编译器可以准确地知道应该调用哪个方法,这种调用方式称为静态绑定;如果调用的方法依赖于隐式参数的实际类型,并且在运行时实现动态绑定
  • 当程序运行,并且采用动态绑定调用方法时,虚拟机一定调用所引用对象的实际类型最适合的那个类的方法

由于每次调用方法都要进行搜索,时间开销较大,所以虚拟机预先为每个类创建了一个方法表,其中列出了所有方法的签名和实际调用的方法

多态的陷阱

注:多态只是针对于普通方法,对于实例变量和静态方法不会存在多态
实例变量在编译时就会被解析

public class Parent {
    public int field = 0;

    public int getField(){
        return field;
    }
}

public class Child extends Parent {
    public int field = 1;

    @Override
    public int getField(){
        return field;
    }
}

public class TestField {
    public static void main(String[] args) {
        Parent parent = new Child();

      // 0
      System.out.println("parent.field= "+parent.field);
// 1
      System.out.println("parent.getField= "+parent.getField());
        Child child = new Child();
      // 1
      System.out.println("child.field= "+child.field);
// 1
      System.out.println("child.getField= "+child.getField());
    }
}

执行结果

parent.field= 0
parent.getField= 1
child.field= 1
child.getField= 1

Parent.field和Child。field被分配了不同的存储空间,Child其实是存在两个filed属性的:本身的以及父类的,但是在引用Child的field的时候,默认的field属性是来自于本身的,如果要获取父类的该实例变量,需要使用super.field来显示地指定获取父类实例变量

对象的实例变量的值取决于声明该变量所用的类型

但是这种情况一般不会发生,首先实例变量一般来说都是私有private的,其次子类和父类一般也不会起相同的实例变量名字

对于静态方法的话,静态方法只与类关联,与对象无关

https://zhhll.icu/2020/java基础/面向对象/5.java基础之继承/

本文由mdnice多平台发布

相关文章

  • 组合模式(Composite)

    在探讨Java组合模式之前,先要明白几个概念的区别:继承、组合和聚合。 继承是is-a的关系。组合和聚合有点像,有...

  • java基础概念

    java_basic 介绍 java基础 三大特性之—封装 三大特性之—继承 三大特性之—多态 抽象 接口 深拷贝...

  • 面向对象原则

    组合复用原则 多用组合, 少用继承 , 用组合代替继承 ,比如在java 分层设计中, service需要用dao...

  • Java基础之组合

    我们已经尝试去定义类。定义类,就是新建了一种类型(type)。有了类,我们接着构造相应类型的对象。更进一步,每个类...

  • java基础(第一篇)继承与组合

    前言 本文讲述上篇文章《java基础(第零篇)对象与类》遗留的问题继承与组合的区别,在讲述区别之前。先讲述继承的有...

  • 继承

    优秀文章 菜鸟教程 > Java 继承clever_fan > 重新认识java(四) — 组合、聚合与继承的爱恨...

  • Java 基础学习笔记

    Java 基础之 面向对象六大原则 Java 基础之 重写和重载的区别和各自使用 Java 基础之巧用Object...

  • 继承之组合继承

    组合原型链和借用构造函数 设计思想:1.使用原型链实现对原型属性和方法的继承:Man3.prototype = n...

  • 组合寄生继承和组合继承

    1.js中实现组合继承(B继承A): function A(name){ this.name = name; ...

  • java小心机(4)| 继承与组合的爱恨情仇

    在java中,有两种主要复用代码的方法:继承和组合。 继承,是OOP的一大特性,想必大家都非常熟悉了;组合,其实也...

网友评论

      本文标题:java基础之组合和继承

      本文链接:https://www.haomeiwen.com/subject/brambdtx.html