You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java继承中super与override的使用场景及代码复用问题

Fixing Duplicate Code in Your Java Inheritance Setup

Hey there! Let's tackle that duplicate code problem you're facing with your Attack and UseForce classes. I'll walk you through a few practical approaches, including using inheritance properly with super/override, and how to extract duplicate code even when you're already tied to a parent class.

1. Reduce Act Method Duplication with Inheritance

The biggest win here is fixing the act() method—most of the logic is identical, only the energy value differs. Here's how to refactor this cleanly:

Step 1: Update the Parent Attack Class

Make the energy value a protected abstract method (or a protected field) so subclasses can provide their own value, while keeping all shared act() logic in the parent class:

public class Attack extends SWAffordance implements SWActionInterface {
    // ... existing code ...

    // Define an abstract method for subclasses to supply required energy
    protected abstract int getRequiredEnergy();

    @Override
    public boolean canDo(SWActor a) {
        SWEntityInterface target = this.getTarget();
        return !a.isDead() && target.getHitpoints() > 0;
    }

    @Override
    public void act(SWActor a) {
        SWEntityInterface target = this.getTarget();
        boolean targetIsActor = target instanceof SWActor;
        SWActor targetActor = null;
        // Use the abstract method to get the energy value
        int requiredEnergy = getRequiredEnergy();

        if (targetIsActor) {
            targetActor = (SWActor) target;
        }
        // ... rest of your shared act() logic goes here ...
    }
}

Step 2: Simplify the UseForce Subclass

Now UseForce only needs to override the energy method (and adjust canDo() if needed)—no more repeating the entire act() method:

public class UseForce extends Attack {
    private int minUsePoints; // Assuming this is defined in your class

    // ... existing code ...

    // Provide the force-specific energy value
    @Override
    protected int getRequiredEnergy() {
        return 2;
    }

    @Override
    public boolean canDo(SWActor a) {
        // If you need to include the parent's canDo logic too, use super.canDo(a)
        // return super.canDo(a) && a.getForcepoints() >= minUsePoints;
        // For your current requirement, keep your original check:
        return a.getForcepoints() >= minUsePoints;
    }
}

If you prefer using a field instead of an abstract method, initialize it in constructors:

// In Attack.java
protected int requiredEnergy;

public Attack() {
    this.requiredEnergy = 1; // Default for Attack
}

// In UseForce.java
public UseForce() {
    this.requiredEnergy = 2; // Override for UseForce
}

Then use this.requiredEnergy in the act() method instead of the abstract method.

2. Extracting Duplicate Code with a Helper Class (When Inheritance Isn't Enough)

Since Attack already inherits from SWAffordance, you can't extend another class—but you can use composition with a helper class to extract shared logic. For example, create a utility class to handle target preparation:

public class AttackTargetHelper {
    // Extract target casting logic into a reusable method
    public static SWActor getTargetAsActor(SWEntityInterface target) {
        return target instanceof SWActor ? (SWActor) target : null;
    }

    // Or a method that handles the entire common setup
    public static void prepareAttackContext(SWEntityInterface target, Consumer<SWActor> targetAction) {
        SWActor targetActor = getTargetAsActor(target);
        // Add any other shared setup logic here
        if (targetActor != null) {
            targetAction.accept(targetActor);
        }
    }
}

Then use this in both classes to avoid repetition:

// In Attack.act()
@Override
public void act(SWActor a) {
    SWEntityInterface target = this.getTarget();
    int requiredEnergy = 1;
    AttackTargetHelper.prepareAttackContext(target, (targetActor) -> {
        // Your attack-specific logic here
    });
    // ... rest of shared logic ...
}

// In UseForce.act()
@Override
public void act(SWActor a) {
    SWEntityInterface target = this.getTarget();
    int requiredEnergy = 2;
    AttackTargetHelper.prepareAttackContext(target, (targetActor) -> {
        // Your force-specific logic here
    });
    // ... rest of shared logic ...
}

This keeps duplicate code centralized in one place, making updates easier later.

3. When to Use super vs override

Let's break down the use cases clearly:

  • override: Use this when you want to replace or extend the parent class's method behavior. For example, UseForce overrides canDo() to add a force points check, or overrides getRequiredEnergy() to provide a different value. Always add the @Override annotation—it catches typos and ensures you're actually overriding a parent method.
  • super: Use this when you want to reuse the parent class's method logic inside your subclass's overridden method. For example, if UseForce's canDo() should also validate the actor is alive and the target has hitpoints (from Attack.canDo()), you'd write:
    @Override
    public boolean canDo(SWActor a) {
        // First run the parent's canDo check, then add our own condition
        return super.canDo(a) && a.getForcepoints() >= minUsePoints;
    }
    
    You can call super.method() anywhere in your subclass method—start, middle, or end—depending on when you need the parent's logic to run.

内容的提问来源于stack exchange,提问作者Sook Lim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:33:12