首页 > 其他分享 >多态

多态

时间:2024-08-05 12:50:27浏览次数:12  
标签:子类 多态 接口 class 方法 public

多态

1.多态的概念

  • 多态是方法或对象具有多种形态,是面向对象的第三大特征
  • 多态前提是两个对象(类)存在继承关系,多态是建立在封装和继承基础之上的。

2.为什么要使用多态

  1. 代码重用和扩展性:
    多态性使得我们可以编写通用的代码,可以适用于各种不同类型的对象。通过抽象类和接口,我们可以定义通用的方法和属性,而具体的实现可以由子类来完成。这种灵活性使得代码更容易被重用和扩展,同时也降低了代码的耦合度。

  2. 简化代码和逻辑:
    多态性使得我们可以通过统一的接口来处理不同类型的对象,从而简化了代码和逻辑。我们不需要为每种具体类型都编写一套独立的逻辑,而是可以通过一个统一的方法来处理所有类型的对象。这种简化的代码结构更易于理解和维护。

  3. 更易于测试和调试:
    由于多态性使得代码更加模块化和可复用,因此更容易进行单元测试和调试。我们可以针对接口或抽象类编写通用的测试用例,而不需要为每个具体的实现编写独立的测试代码。这样可以提高测试效率,降低测试成本。

  4. 扩展性和灵活性:
    多态性使得程序具有更强的扩展性和灵活性。当需要添加新的功能或修改现有功能时,我们可以通过添加新的子类或修改现有子类来实现,而不需要修改现有的代码。这种低耦合度的设计使得程序更容易适应变化,并且更容易进行维护和升级。

  5. 可替换性:
    多态性允许我们将父类的引用指向子类的对象,从而实现了对象的替换。这种特性使得程序更具灵活性,可以在运行时动态地替换对象的实现,而不需要修改代码。这种可替换性使得程序更容易适应不同的需求和环境。

3.多态的分类

1.1 编译时多态(静态绑定)
编译时多态指的是方法重载(Method Overloading),即同一个类中可以有多个同名的方法,但它们的参数列表不同。编译器会在编译时根据方法的参数列表决定调用哪个方法。

public class OverloadExample {
    public void display(int a) {
        System.out.println("Argument: " + a);
    }

public void display(String a) {
    System.out.println("Argument: " + a);
}

public static void main(String[] args) {
    OverloadExample obj = new OverloadExample();
    obj.display(10);     // 输出:Argument: 10
    obj.display("Hello"); // 输出:Argument: Hello
}

}

1.2 运行时多态(动态绑定)
运行时多态指的是方法重写(Method Overriding),即子类可以重写父类的方法。在运行时,JVM根据对象的实际类型调用相应的方法。

class Animal {
    public void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks");
    }
}

class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("Cat meows");
    }
}

public class TestPolymorphism {
    public static void main(String[] args) {
        Animal myAnimal = new Animal();
        Animal myDog = new Dog();
        Animal myCat = new Cat();

​    myAnimal.sound(); // 输出:Animal makes a sound
​    myDog.sound();    // 输出:Dog barks
​    myCat.sound();    // 输出:Cat meows
}

}

4.多态的机制原理

RTTI

多态实现的技术基础是 RTTI,即 Run-Time Type Identification(运行时类型判定),它的作用是在我们不知道某个对象的确切的类型信息时(即某个对象是哪个类的实例),可以通过 RTTI 相关的机制帮助我们在编译时获取对象的类型信息。

而 RTTI 的功能主要是通过 Class 类文件实现的,更精确一点来说,是通过 Class 类文件的方法表实现的。

这里提到的 Class 类可以理解为是 “类的类”(class of classes)。如果说类是对象的抽象的话,那么 Class 类就是对类的抽象。而每个类都有一个 Class 对象,每当编写并且编译成功一个新的类,就会生成一个对应的 Class 对象,被保存在一个与类同名的 .class 文件中。

详细一点来说,就是 Java 源码编译器将 Java 文件编译成 .class 文件,然后通过类装载器将 .class 文件装载到 JVM 中,并在内部建立该类的类型信息(.class 文件在 JVM 中存储的一种数据结构),最后通过执行引擎来执行。

方法表是实现多态的关键所在,里面保存的是实例方法的引用,且是直接引用。Java 虚拟机在执行程序时,就是通过方法表来确定运行哪一个多态方法的。

多态方法调用

在调用方法时,首先需要完成实例方法的符号引用解析,也就是将符号引用解析为方法表的偏移量。

虚拟机通过对象引用得到方法区中类型信息的入口,查询类的方法表,当将子类对象声明为父类类型时,形式上调用的是父类方法;

此时虚拟机会从实际类的方法表(虽然声明的是父类,但是实际上这里的类型信息中存放的是子类的信息)中根据偏移量获取该方法名对应的指针,进而就能指向实际类的方法了。

上面我们讨论的仅是利用继承实现多态的内部机制,多态的另外一种实现方式:接口实现相比而言会更加复杂。原因在于,Java的单继承保证了类的线性关系,而接口可以同时实现多个,这样光凭偏移量就很难准确获得方法的指针。

所以在 JVM 中,多态的实例方法调用实际上有两种指令:

invokevirtual 指令:用于调用声明为类的方法;
invokeinterface 指令:用于调用声明为接口的方法。
当使用 invokeinterface 指令调用方法时,就不能采用固定偏移量的办法了。实际上,Java 虚拟机对于接口方法的调用是采用搜索方法表的方式来实现的,比如,要在 Father 接口的方法表中找到 dealHouse() 方法,必须搜索 Father 的整个方法表。所以我们可以得出,在性能上,调用接口引用的方法通常总是比调用类的引用的方法要慢。这也告诉我们,在类和接口之间优先选择接口作为设计并不总是正确的。

以上就是多态的原理,总结起来说就是两点:

方法表起了决定性作用,如果子类改写了父类的方法,那么子类和父类的同名方法共享一个方法表项,都被认作是父类的方法,因此可以写成父类引用指向子类对象的形式。
类和接口的多态实现不一样,类的方法表可以使用固定偏移,但接口需要进行搜索,原因是接口的实现不是确定唯一的,所以相对来说性能差一些。

标签:子类,多态,接口,class,方法,public
From: https://www.cnblogs.com/zpjd/p/18342995

相关文章

  • 多态,抽象,接口,Object,Equals
    1.多态1.1编译时多态:在编译时就能够确定调用哪个方法​方法重载是编译时多态,在编译期根据参数的数据类型,个数以及次序来确定调用方法1.2运行时多态:只有在运行时才能确定调用哪个方法,主要指动态绑定来实现,动态绑定是程序运行时确定调用哪个方法的过程,他依赖于对......
  • 【C++】多态 - 含3个案例
    目录一、多态分类二、多态区别三、多态基本语法四、多态原理五、案例1:计算机类六、纯虚函数和抽象类七、案例2:制作饮品八、虚析构和纯虚析构九、案例3:电脑组装需求分析及实现多态是C++面向对象三大特性之一一、多态分类①静态多态:函数重载、运算符重载、复用函......
  • 面向对象进阶:多态、内部类、常用API
    目录 Java中的接口Java中的内部类 常用APIStringBuilder类Java高级面向对象编程在这篇博客文章中,我们将探索Java中的高级面向对象编程概念,包括接口、内部类和常用API。每个概念都将通过代码示例来演示它们的应用。 Java中的接口 什么是接口?接口是Java中的一种引......
  • 抽象和多态的关系
    接口和多态的关系多态性的基础:接口是实现多态性的关键机制之一。通过接口,不同的类可以实现相同的方法,但具体的实现可以各不相同。方法重载:多态性允许同一个方法名在不同的类中有不同的实现。接口定义了这些方法的统一签名,而实现类提供了具体的实现细节。动态绑定......
  • 多态
    目录多态的基本概念概念多态的定义与使用格式实例多态成员的特点实例多态中向上转型与向下转型实例多态的优点多态的基本概念概念多态是继封装、继承之后,面向对象的第三大特性。现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两......
  • 多态的概念
    多态多态(Polymorphism)是面向对象编程(OOP)的一个核心概念,它指的是同一个接口可以被多个对象以不同的方式实现。多态性使得代码更加灵活,易于扩展和维护。多态性的类型编译时多态(StaticPolymorphism)或方法重载(MethodOverloading):这是在编译时期就确定的多态性,通过方法名和参......
  • 接口和多态的关系
    接口和多态的关系多态性的基础:接口是实现多态性的关键机制之一。通过接口,不同的类可以实现相同的方法,但具体的实现可以各不相同。方法重载:多态性允许同一个方法名在不同的类中有不同的实现。接口定义了这些方法的统一签名,而实现类提供了具体的实现细节。动态绑......
  • 多态
    多态(Polymorphism)多态(Polymorphism)是面向对象编程中的一个核心概念,它指的是同一种类型的对象在不同的情况下表现出不同的行为。以下是对多态概念的详细解释:一、多态的定义基本定义:多态通俗来说就是多种形态,具体表现为去完成某个行为时,当不同的对象去完成时会产生出不同的状......
  • 多态
    多态1.多态的概念多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作,如下图多态性是对象多种表现形式的体现。现实中,比如我们按下F1键这个动作:如果当前在Flash界面下弹出的就是AS3的帮助文档;如果当前在Word下......
  • 【C++】多态
    什么是多态?就是不同对象在完成某个行为时,会产生不同的形态多态分为静态多态和动态多态静态多态在编译期间就确定执行哪个函数,主要包含:函数重载和运算符重载静态多态函数的地址早绑定-在编译阶段确定函数的地址动态多态派生类和虚函数实现的运行阶段的多态动态多态函数......