Java遍历父类集合时调用子类print方法的最优实现方案
这其实是Java多态特性的典型应用场景,完全不需要用instanceof这种破坏面向对象设计的写法,咱们一步步来理清楚正确的实现方式:
最优实现:利用多态+抽象方法
核心思路是让父类定义行为的契约,子类实现具体行为,遍历的时候直接调用父类的方法,Java的多态机制会自动帮你找到对应子类的实现。
1. 父类Train定义抽象print方法
因为Train作为父类,本身不应该有具体的打印逻辑(毕竟它只是一个抽象的火车类型),所以把它定义为抽象类,并声明抽象的print方法,强制所有子类必须实现这个方法:
abstract class Train { // 定义抽象方法,子类必须实现 public abstract void print(); }
2. 子类实现各自的print方法
让Intercity和Sprinter分别重写print方法,输出各自对应的字符串:
class Intercity extends Train { @Override public void print() { System.out.println("intercity"); } } class Sprinter extends Train { @Override public void print() { System.out.println("sprinter"); } }
3. 遍历列表直接调用print方法
遍历Train类型的列表时,不需要任何类型判断,直接调用每个对象的print方法即可,多态会自动触发对应子类的实现:
import java.util.ArrayList; import java.util.List; public class TrainDemo { public static void main(String[] args) { List<Train> trains = new ArrayList<>(); trains.add(new Intercity()); trains.add(new Sprinter()); trains.add(new Intercity()); // 遍历调用print,自动匹配子类实现 for (Train train : trains) { train.print(); } } }
为什么这比instanceof的写法更好?
- 符合开闭原则:以后如果新增其他火车子类(比如
RegionalTrain),只需要实现print方法即可,完全不需要修改遍历的代码。 - 代码更简洁易维护:去掉了冗余的类型判断逻辑,避免了强制类型转换可能带来的错误。
- 遵循面向对象设计:把具体行为的实现交给子类,父类只定义抽象契约,完美发挥了多态的优势。
如果特殊场景下Train不能是抽象类(比如需要实例化Train对象),也可以在父类写一个默认的print实现(比如输出"train"),子类依然可以重写它来覆盖默认行为,同样不需要instanceof。
内容的提问来源于stack exchange,提问作者Just van der Veeken




