目录
一个生动形象的例子
场景设定
1. 方法重写(Method Overriding)
2. 动态绑定(Dynamic Binding)
3. 多态(Polymorphism)
归纳关系:
重写
概念
条件
重写的示例
重载与重写的区别
动态绑定
定义:
多态性的实现:
与静态绑定的区别:
示例:
多态
定义
实现方式
实现原理
应用场景
示例
意义
一个生动形象的例子
场景设定
想象一个汽车制造厂,其中有不同类型的车辆,如轿车、SUV和卡车。每种车辆都有自己独特的驾驶行为,但它们都继承自一个基本的“汽车”类。
1. 方法重写(Method Overriding)
- 定义:子类提供与父类相同方法名、参数列表和返回值类型的方法,以覆盖父类中的方法。
在这个例子中,假设“汽车”类有一个名为“drive”的方法,它输出“汽车正在行驶”。但是,轿车、SUV和卡车在行驶时可能有不同的表现,因此它们各自重写了“drive”方法。
- 轿车类重写“drive”方法:输出“轿车平稳行驶”。
- SUV类重写“drive”方法:输出“SUV越野行驶”。
- 卡车类重写“drive”方法:输出“卡车重载行驶”。
2. 动态绑定(Dynamic Binding)
- 定义:在运行时根据对象的实际类型来确定调用哪个重写后的方法。
现在,假设制造厂有一个测试驾驶员,他只需要知道如何“驾驶”(即调用“drive”方法),而不需要知道具体是哪种车型。当他驾驶不同类型的汽车时,会动态地绑定到相应车型重写的“drive”方法上。
3. 多态(Polymorphism)
- 定义:允许一个接口(或父类引用)引用多种实际类型,并根据实际类型执行对应的方法。
在测试中,驾驶员可以驾驶不同类型的汽车,而每种车型在行驶时展现出不同的行为,这就是多态的体现。虽然驾驶员都是通过调用“drive”方法来驾驶汽车,但具体的行驶表现却因车型的不同而不同。
归纳关系:
- 方法重写是实现多态的基础,子类通过重写父类的方法以提供自己独特的行为。
- 动态绑定则使得在运行时能够根据实际对象的类型来调用相应重写后的方法,从而实现多态的效果。
- 多态则是这些技术综合应用的结果,它允许我们使用统一的接口(如本例中的“drive”方法)来处理不同类型的对象,并在运行时展现出各自独特的行为。
重写
概念
方法重写,是面向对象编程中的一个重要概念,特别是在Java这样的面向对象的编程语言中。方法重写允许子类提供一个与父类中已有方法具有相同方法签名(即方法名和参数列表相同)的实现。
通过方法的重写,子类可以改变或扩展从父类继承的方法的行为。
条件
在Java中,要进行方法重写,必须满足以下条件:
- 方法名和参数列表必须与父类中被重写的方法相同:
这是为了确保在运行时能够正确地识别和调用重写的方法。
- 访问修饰符不能低于父类方法的访问修饰符:
例如,如果父类方法时 public 的,那么重写该方法的方法也必须时 public 的。
- 返回类型必须与父类中被重写的方法的返回类型相同
- 子类方法抛出的异常类型必须是父类方法所抛出异常类型的子集:
子类方法可以不抛出异常,或者抛出与父类方法相同的异常或其子类型的异常。
- 被重写的方法不能是 final 或 static 方法:
final 方法不能被重写,而 static 方法与类关联而非实例关联,因此也不适用于重写
重写的示例
下面是一个简单的Java示例,展示了如何重写父类的方法:
class Animal {
public void makeSound() {
System.out.println("Some generic animal sound");
}
}
class Dog extends Animal {
@Override // 注解表明此方法是重写父类方法
public void makeSound() {
System.out.println("Bark");
}
}
public class MethodOverridingExample {
public static void main(String[] args) {
Animal animal = new Dog(); // Animal类型的引用指向Dog类型的对象
animal.makeSound(); // 输出"Bark",因为Dog类重写了makeSound方法
}
}
在这个例子中,Dog 类继承了 Animal 类,并重写了 makeSound 方法。当我们通过 Animal 类型的引用调用 makeSound 方法时,实际上调用的是 Dog 类中重写后的 makeSound 方法,输出“Bark”。
重载与重写的区别
- 重写发生在父类和子类之间,子类提供与父类相同方法签名的新实现。
- 重载发生在同一个类中,允许多个方法拥有相同的名字,但参数列表不同(参数数量、类型或顺序不同)。
动态绑定
在Java中,动态绑定(Dynamic Binding)是一个核心概念,它允许在运行时根据对象的实际类型来确定调用哪个方法。这种机制是实现多态性的关键,使得程序能够在运行时灵活地处理不同类型的对象。
定义:
动态绑定是指在程序运行过程中,根据具体的实例对象来确定调用哪个方法的过程。它不同于静态绑定(前期绑定),后者在编译时就已经确定了方法的调用关系。
多态性的实现:
- 动态绑定是实现多态性的重要因素。多态性允许我们使用父类类型的引用来引用子类的对象,并在运行时确定实际调用的方法。这种机制增加了程序的灵活性和可扩展性。
- 例如,假设有一个父类 Animal 和一个子类 Dog ,Dog 类重写了 Animal 类的 makeSound() 方法。当我们创建一个 Dog 对象并将其赋值给一个 Animal 类型的引用时,通过该引用调用 makeSound() 方法,会动态地绑定到 Dog 类的实现上。
与静态绑定的区别:
- 静态绑定(也称为前期绑定或编译时绑定)是在编译时就已经确定了方法的调用关系。它通常用于调用静态方法、私有方法、构造方法以及使用 final 修饰的方法等。
- 动态绑定则是在运行时根据对象的实际类型来确定方法的调用关系。它主要用于实现多态性,使得程序能够更加灵活和可扩展。
示例:
class Animal {
void makeSound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Bark");
}
}
public class DynamicBindingExample {
public static void main(String[] args) {
Animal animal = new Dog(); // 向上转型
animal.makeSound(); // 动态绑定到Dog类的makeSound()方法上
}
}
在上述示例中,当我们通过父类类型的引用 animal 调用 makeSound() 方法时,会动态地绑定到 Dog 类的实现上,输出“Bark”。这就是动态绑定的一个典型应用示例。
注意事项:
- 动态绑定只适用于实例方法,不适用于静态方法、私有方法和构造方法。这是因为这些方法在编译时就已经确定了调用关系,无法进行动态绑定。
- 使用 final 修饰的方法也无法进行动态绑定,因为它们不能被重写。
多态
在Java编程语言中,多态性是面向对象编程的三大特性之一,它允许一个接口(或基类引用)被多种数据类型所实现,并根据实际的类型执行对应的方法。以下是关于Java中多态的详细介绍:
定义
多态(Polymorphism)是指允许一个接口(或父类引用)引用多种实际类型,并且可以根据实际的类型来执行对应的方法。简言之,就是同一个方法调用可以有不同的实现方式。
实现方式
Java中多态的实现主要依赖于继承和方法重写。
- 继承:子类可以继承父类的方法定义和属性,从而具备相同的方法签名。
- 方法重写(覆盖):子类可以对继承自父类的方法进行重写,即在子类中重新定义与父类相同签名的方法。
实现原理
多态的实现原理主要基于动态绑定(Dynamic Binding),也称为后期绑定。在运行时,Java虚拟机会根据对象的实际类型来确定调用哪个重写后的方法。这种机制使得相同的消息(即方法调用)可以根据不同的对象而具有不同的行为。
应用场景
多态在Java编程中有广泛的应用,以下是几个常见的应用场景:
- 接口和抽象类的使用:通过定义接口或抽象类,并在父类中声明一组方法,具体实现留给子类。这样,不同的子类可以实现各自独特的行为。
- 方法重写和回调机制:在父类中定义一个回调方法,子类重写该方法,并由父类对象调用。这样,根据不同的子类实现,可以执行相应的逻辑。
示例
假设有一个 Animal 类和两个子类 Dog 和 Cat,每个类都有一个 makeSound 方法。通过多态,我们可以使用一个 Animal 类型的引用来引用 Dog 或 Cat 对象,并调用它们的 makeSound 方法。在运行时,Java虚拟机会根据对象的实际类型(Dog 或 Cat)来确定调用哪个实现。
Animal animal1 = new Dog();
Animal animal2 = new Cat();
animal1.makeSound(); // 输出 "Woof!"
animal2.makeSound(); // 输出 "Meow!"
意义
多态性提高了代码的灵活性和可扩展性。通过多态,我们可以编写更加通用的代码,而无需关心具体的实现细节。这使得代码更加易于维护和扩展。
注意事项
- 多态只适用于实例方法,不适用于静态方法。因为静态方法与类关联,而不是与实例关联。
- 多态的实现需要满足两个条件:一是方法必须在子类中被重写;二是必须通过父类引用