简体   繁体   中英

Best way to share common code between two classes

I got two classes, Player and Enemy, and both share a few standard methods that I do not want to duplicate. The player and Enemy class already extend an another class, so making an abstraction class won't help.

Player Class:

public class Player extends Game {

public void getPlayer() {
        //imp
        return Player;
    }
@Override
public void getWorld() {
        return world;
    }
}

Enemy Class

public class Enemy extends Game {

public void getPlayer() {
        //imp
        return Player;
    }
@Override
public void getWorld() {
        return world;
    }
}

Before worrying about sharing code, you must first fix this glaring mistake: public class Player extends Game { . There is no way on earth that either class above should extend from Game, none since a "Player" cannot satisfy the logical "is-a" relationship to Game. Using other games as an analogy, should a chess piece extend a ChessGame class? Is a chess piece a more specialized sub-type of chess game? No. The game holds chess pieces, a "has-a" relationship exists, not an "is-a" relationship.

Instead there is a "has-a" relationship, possibly in both directions since Game will obviously hold references to Players and Enemies, and possibly Player and Enemy might need references to the single Game instance. So, in short, the relationship should be one of composition: give the classes a Game field, if a direct relationship is needed, and feed in the Game instance via constructor parameter or setter.

Fixing this will get rid of your issue:

The player and Enemy class already extend an another class, so making an abstraction class won't help.

Then I would give Player and Enemy a common abstract type to inherit from, say AbstractPlayer, and it can be either an interface or an abstract class, depending on all your requirements.

If you need to use an outside Game class in your program, either use it directly, or have another class, say MyGame, inherit from Game.

Something like:

public abstract class AbstractPlayer {
    private Game game;
    private String name;
    
    public AbstractPlayer(String name, Game game) {
        this.name = name;
        this.game = game;
    }
    
    public World getWorld() {
        // if game has this method, ... which we currently don't know
        return game.getWorld();
    }
    
    // ... other methods and fields
}

and then,

public class Player extends AbstractPlayer {
    public Player(String name, Game game) {
        super(name, game);
        // .....
    }
}
public class MyGame extends Game {
    private AbstractPlayer player;
    private AbstractPlayer enemy;
    
    // ....
}

Side note, this:

public void getPlayer() {
        //imp
        return Player;
    }

doesn't make sense, since you're creating a getter that returns itself, the this . No need for this here.

Nor does this:

public void getWorld() {
   return world;
}

since you're declaring a getter as a void method, and then returning something from it.

Yes, making an abstraction class will help, since Player and Enemy both extend the same class. Therefore you can create an abstraction class (eg PlayerEnemyBase) with PlayerEnemyBase extends Game which defines the shared behaviour and then have Player and Enemy extend PlayerEnemyBase.

However, I agree with Hovercraft that having Player extend Game seems a bit strange since inheritance in java is meant to model an Is-A relationship.

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