Shades
Shades

Reputation: 5616

Enum in inheritance

I have multiple classes deriving from one base class with a polymorphic method that accepts the enum type declared in the base class. I repeat the enum in the subclasses so that each subclass only accepts its own specific group of values:

class Character {

    enum Actions {

    }

    func performAction(action: Actions) {
        // Functions to be performed by all subclasses
    }
}


class Warrior: Character {

    enum Actions {
        case Attack, Block, Charge
    }

    override func performAction(action: Actions) {
        // Add subclass-specific behavior
    }
}

class Wizard: Character {

    enum Actions {
        case Attack, CastSpell, Run
    }

    override func performAction(action: Actions) {
        // Add subclass-specific behavior
    }
}

This of course doesn't work and I get

'Actions' is ambiguous for type lookup in this context.

I can't delete the enum in the base class because then I get an undeclared type error for the method. I have a strong feeling I'm going about this all wrong and trying to reinvent the wheel. Can someone point me in the right direction? Thank you.

Upvotes: 0

Views: 480

Answers (1)

Cristik
Cristik

Reputation: 32782

How about this approach:

enum Action {
    case Attack, Block, Charge, CastSpell, Run
}

class Character {

    final func performAction(action: Action) {
        if self.allowedActions().contains(action) {
            self.executeAction(action);
        }
    }

    func allowedActions() -> [Action] {
        // to be overriden in subclasses
        return []
    }

    func executeAction(action: Action) {
        // this will also be overriden in subclasses
    }
}

class Warrior: Character {
    override func allowedActions() -> [Action] {
        return [.Attack, .Block, .Charge]
    }

    override func executeAction(action: Action) {
        // do whatever is needed
    }
}

class Wizard: Character {
    override func allowedActions() -> [Action] {
        return [.Attack, .CastSpell, .Run]
    }

    override func executeAction(action: Action) {
        // do whatever is needed
    }
}

You use one enum to hold all possible actions, and you define per subclass which actions are allowed.

This way you can treat all characters the same: ask for the actions they can perform, so you can show a menu for example, and then ask the character to perform that action.

We can go even further, by using structs instead of classes and associated values for enums, this being a more swift-ish approach, but also a little bit more complicated to setup (but more logical).

Upvotes: 1

Related Questions