You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Java SE 8游戏开发:已有父类无法移除时如何在extends中加两个类

Java SE 8 中已有父类时扩展功能的替代方案

嘿,这个问题我太熟了——Java 从设计之初就只支持单继承,所以你没法直接在extends后面加第二个类。不过别担心,有两个非常实用的方案能帮你实现类似多继承的效果,而且在Java SE 8里还能借助新特性让代码更优雅!

方案一:使用接口(含Java 8默认方法)

Java 8 给接口带来了默认方法的特性——接口里可以写带实现逻辑的方法,这就允许你把想要“继承”的第二个类的行为抽象到接口中,然后让你的游戏类实现这个接口,直接复用默认方法的逻辑。

举个实际例子:假设你现在的游戏类已经继承了Character父类,现在想加入DamageCalculator类的伤害计算功能,就可以这么做:

// 把要扩展的伤害计算功能抽象成接口,用默认方法实现核心逻辑
interface DamageCalculable {
    default int calculateAttackDamage(int baseAttack, int level) {
        return baseAttack * level / 10 + 5;
    }
}

// 你的游戏类:继承现有父类 + 实现功能接口
public class GamePlayer extends Character implements DamageCalculable {
    public void attackEnemy() {
        // 直接使用接口的默认方法
        int damage = calculateAttackDamage(getBaseAttack(), getLevel());
        System.out.println("对敌人造成了 " + damage + " 点伤害");
    }
}

需要注意的是:接口不能定义实例变量(状态),如果你要扩展的类本身带有自己的成员变量(比如伤害计算的系数配置),那这个方案就不太适用了——这时候可以用下面的组合方案。

方案二:组合(Composition)+ 委托(Delegation)

这是更灵活的一种方案,遵循“多用组合,少用继承”的设计原则:你不需要继承第二个类,而是把它作为当前类的一个成员变量,然后在当前类中写对应的方法,把请求委托给这个成员变量来处理。

还是用刚才的例子:

// 保留你想扩展的原类的完整实现
public class DamageCalculator {
    // 假设这个类有自己的状态(实例变量)
    private int damageCoefficient = 10;

    public int calculateAttackDamage(int baseAttack, int level) {
        return baseAttack * level / damageCoefficient + 5;
    }

    public void logDamage(int damage) {
        System.out.println("记录伤害值:" + damage);
    }
}

// 你的游戏类:继承现有父类 + 组合DamageCalculator
public class GamePlayer extends Character {
    // 把要扩展的类作为成员变量
    private DamageCalculator damageCalc = new DamageCalculator();

    // 对外暴露和DamageCalculator一致的方法,内部委托给成员变量
    public int calculateAttackDamage(int baseAttack, int level) {
        return damageCalc.calculateAttackDamage(baseAttack, level);
    }

    public void logDamage(int damage) {
        damageCalc.logDamage(damage);
    }

    public void attackEnemy() {
        int damage = calculateAttackDamage(getBaseAttack(), getLevel());
        logDamage(damage);
    }
}

这种方案的优势在于:

  • 可以保留原类的所有状态和逻辑,不需要重构
  • 代码耦合度更低,后续如果要替换DamageCalculator的实现,只需要修改成员变量的实例化逻辑即可
  • 完全符合Java的单继承设计约束

总结一下怎么选

  • 如果要扩展的是无状态的行为逻辑:优先用带默认方法的接口,代码更简洁
  • 如果要扩展的类带有自己的状态(成员变量),或者你需要保留原类的完整实例逻辑:用组合+委托的方案

内容的提问来源于stack exchange,提问作者Corentin de Maupeou

火山引擎 最新活动