Java作为典型的面向对象编程语言,继承和多态是其核心特性,两者的结合使用能有效提升代码的复用性和扩展性,是Java开发者必须掌握的基础能力。很多初学者会困惑继承和多态的关系,以及如何在代码中正确运用两者的结合逻辑。

继承与多态的基本概念
继承是指子类可以复用父类的属性和方法,同时可以扩展自己的独有功能,通过extends关键字实现。多态则是指同一个行为具有多个不同表现形式的能力,通常依赖继承、方法重写和向上转型来实现。
继承是多态的基础,没有继承关系就不存在子类对父类方法的重写,也就无法形成多态的表现形式。两者的结合可以让代码更灵活,比如定义统一的父类引用,指向不同的子类实例,调用相同方法时执行不同的逻辑。
继承与多态结合的核心实现
1. 方法重写
方法重写是子类对父类中允许访问的方法的实现逻辑进行重新编写,要求方法名、参数列表、返回值类型必须和父类一致,访问权限不能比父类更严格。
以下是一个简单的父类定义:
// 父类:动物类
public class Animal {
// 父类的通用方法
public void makeSound() {
System.out.println("动物发出声音");
}
// 父类的方法,子类可以重写
public void eat() {
System.out.println("动物吃东西");
}
}
对应的子类实现如下:
// 子类:狗类,继承Animal
public class Dog extends Animal {
// 重写父类的makeSound方法
@Override
public void makeSound() {
System.out.println("狗汪汪叫");
}
// 子类扩展的独有方法
public void guard() {
System.out.println("狗看家护院");
}
}
// 子类:猫类,继承Animal
public class Cat extends Animal {
// 重写父类的makeSound方法
@Override
public void makeSound() {
System.out.println("猫喵喵叫");
}
// 子类扩展的独有方法
public void catchMouse() {
System.out.println("猫抓老鼠");
}
}
2. 向上转型与多态调用
向上转型是指将子类实例赋值给父类引用变量,这是多态的典型表现。此时通过父类引用调用被子类重写的方法时,会执行子类的实现逻辑,而不是父类的方法。
public class Test {
public static void main(String[] args) {
// 向上转型:父类引用指向子类实例
Animal animal1 = new Dog();
Animal animal2 = new Cat();
// 调用重写的方法,执行子类的逻辑
animal1.makeSound(); // 输出:狗汪汪叫
animal2.makeSound(); // 输出:猫喵喵叫
// 调用未重写的方法,执行父类的逻辑
animal1.eat(); // 输出:动物吃东西
}
}
3. 向下转型与独有方法调用
如果需要调用子类独有的方法,就需要将父类引用向下转型为对应的子类类型,转型前需要通过instanceof关键字判断引用实际指向的实例类型,避免类型转换异常。
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();
// 判断animal实际指向的是否是Dog类型
if (animal instanceof Dog) {
// 向下转型
Dog dog = (Dog) animal;
// 调用子类独有方法
dog.guard(); // 输出:狗看家护院
}
// 错误的向下转型,会抛出ClassCastException
// Cat cat = (Cat) animal;
}
}
实践中的注意事项
- 不要滥用继承,只有当子类确实是父类的一种特殊类型时,才使用继承关系,否则可以考虑组合的方式实现功能复用。
- 重写方法时记得添加
@Override注解,编译器会帮你检查方法是否符合重写规则,减少出错概率。 - 向下转型前必须做类型判断,避免
ClassCastException异常,这是多态使用中常见的错误点。 - 父类的私有方法不能被重写,静态方法也不存在多态特性,调用时看引用类型而不是实例类型。
实际应用场景示例
在支付场景中,我们可以定义统一的支付父类,不同的支付方式作为子类,通过多态实现统一的支付调用逻辑,后续新增支付方式只需要新增子类即可,不需要修改原有调用代码。
// 支付父类
public abstract class Payment {
// 抽象支付方法,子类必须实现
public abstract void pay(double amount);
}
// 支付宝支付子类
public class Alipay extends Payment {
@Override
public void pay(double amount) {
System.out.println("使用支付宝支付:" + amount + "元");
}
}
// 微信支付子类
public class WechatPay extends Payment {
@Override
public void pay(double amount) {
System.out.println("使用微信支付:" + amount + "元");
}
}
// 支付调用类
public class PaymentService {
public void processPay(Payment payment, double amount) {
// 多态调用,传入不同的子类实例执行不同的支付逻辑
payment.pay(amount);
}
public static void main(String[] args) {
PaymentService service = new PaymentService();
// 调用支付宝支付
service.processPay(new Alipay(), 100.5);
// 调用微信支付
service.processPay(new WechatPay(), 200.0);
}
}
这种写法符合开闭原则,新增支付方式时只需要新增Payment的子类,不需要修改PaymentService的代码,大大提升了代码的可维护性。