简体   繁体   中英

Abstract methods without abstract classes

I'm kinda new to Java, and I'm trying to write an RPG of sorts.

Now, in the game the player character would have skills. These could be very diverse, from hurting enemies to healing the player and a lot of other things. It'd make sense to create a Skill class with an abstract applyEffect() method, to be defined on each particular skill.

However, I cannot have a non-abstract class containing abstract methods, and every skill should be an object of the Skill class, so it can't be abstract. The obvious solution is to make the Skill class abstract and create a subclass for every single skill, and then instantiate that into an object to use. This approach seems a bit redundant. Is there anything else I could conceivably do in this situation?

EDIT: While we're at it, if I want an object that will appear a single time with standard variables, is there any workaround to making a class just for that one object and then instantiating it?

How about this:

public abstract class Skill {
    public abstract void applyEffect();
}


... somewhere else ... 
Skill dig = new Skill() {
    @Override
    public void applyEffect() {
        doSomeDigging();
    }
};

This one still creates a subclass in the background, but you might like it better.

I would not write skills (like 'heal' and 'hide') as classes. I view classes as objects (players), and methods as abilities (skills). Skills like 'heal' or 'hide' are clearly better as methods than classes.

I would simply have one class that has all methods, but only the selected ones are available for use. Having the skills as enums isn't a bad idea either.

enum Skill {
    HEAL, HIDE, ATTACK, THROW
}

class Player {
    boolean canHeal = false;
    boolean canHide = false;
    boolean canAttack = false;
    boolean canThrow = false;

    Player(Skill[] skills) {
        for(skill : skills) {
            switch(skill) {
                case Skills.HEAL: canHeal = true;
                break;

                case Skills.HIDE: canHide = true;
                break;

                case Skills.ATTACK: canAttack = true;
                break;

                case Skills.THROW: canThrow = true;
                break;

                default: //error
            }
        }
    }

    void heal() {
        [...]
    }
    void hide() {
        [...]
    }
    void attack() {
        [...]
    }
    void throw() {
        [...]
    }
    boolean canHeal() {
        return canHeal;
    }
    boolean canHide() {
        return canHide;
    }
    boolean canAttack() {
        return canAttack;
    }
    boolean canThrow() {
        return canThrow;
    }
}

Now the players can be restricted to only use the methods that should be available to them. What I would do is probably to write a GameHandler-class to take care of everything and do all the checking there.

i would use enums also, you can stuff a bunch of login in them. the maps let each player have whatever skills and stats they need. you can nest enums like this or that .

import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
public class So36107587 {
    enum Stat {
        food,health,magic;
    }
    enum Skill {
        heal,hurt,hunt;
        static void apply(Skill skill,double amount,Player player) {
            double a=amount*random.nextDouble(),x;
            switch(skill) {
                case heal:
                    x=player.stats.get(Stat.health);
                    player.stats.put(Stat.health,a+x);
                    break;
                case hurt:
                    x=player.stats.get(Stat.health);
                    player.stats.put(Stat.health,a-x);
                    break;
                case hunt:
                    x=player.stats.get(Stat.food);
                    player.stats.put(Stat.food,a+x);
                    break;
            }
        }
        static final Random random=new Random();
    }
    static class Player {
        Player() {
            init();
        }
        void init() {
            for(Stat stat:Stat.values())
                stats.put(stat,1.);
            for(Skill skill:Skill.values())
                skills.put(skill,1.);
        }
        void apply(Skill skill,Player player) {
            Skill.apply(skill,skills.get(skill),player);
        }
        @Override public String toString() {
            return ""+skills+" "+stats;
        }
        final Map<Stat,Double> stats=new TreeMap<>();
        final Map<Skill,Double> skills=new TreeMap<>();
    }
    public static void main(String[] args) {
        Player player=new Player();
        System.out.println(player);
        player.apply(Skill.heal,player);
        System.out.println(player);
        player.apply(Skill.hunt,player);
        System.out.println(player);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM