在两个类之间共享常见代码的最佳方法

发布于 2025-01-20 01:38:35 字数 488 浏览 2 评论 0原文

我有两个类,Player 和 Enemy,它们共享一些我不想重复的标准方法。玩家和敌人类已经扩展了另一个类,因此创建抽象类不会有帮助。

玩家等级:

public class Player extends Game {

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

敌人等级

public class Enemy extends Game {

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

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;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

对岸观火 2025-01-27 01:38:35

在担心共享代码之前,您必须首先修复这个明显的错误:public class Player extends Game {。上面的任何一个类都不可能从 Game 扩展,,因为“玩家”无法满足与 Game 的逻辑“is-a”关系。以其他游戏为例,棋子是否应该继承 ChessGame 类?棋子是国际象棋游戏中更专业的子类型吗?不。游戏持有棋子,存在“有一个”关系,而不是“是一个”关系。

相反,存在一种“有一个”关系,可能是双向的,因为游戏显然会保存对玩家和敌人的引用,并且可能玩家和敌人可能需要对单个游戏实例的引用。因此,简而言之,这种关系应该是组合关系之一:如果需要直接关系,则为类提供一个 Game 字段,并通过构造函数参数或 setter 传入 Game 实例。

解决这个问题将解决您的问题:

玩家和 Enemy 类已经扩展了另一个类,因此创建抽象类不会有帮助。

然后,我会给 Player 和 Enemy 一个共同的抽象类型来继承,比如 AbstractPlayer,它可以是一个接口,也可以是一个抽象类,具体取决于您的所有需求。

如果您需要在程序中使用外部 Game 类,可以直接使用它,或者使用另一个类(例如 MyGame)继承自 Game。

类似于:

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
}

然后,

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;
    
    // ....
}

旁注, this:

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

没有意义,因为您正在创建一个返回自身的 getter,即 this。这里不需要这个。

这也不是:

public void getWorld() {
   return world;
}

因为您将 getter 声明为 void 方法,然后从中返回一些内容。

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.

忆伤 2025-01-27 01:38:35

是的,创建一个抽象类会有所帮助,因为 Player 和 Enemy 都扩展同一个类。因此,您可以使用 PlayerEnemyBase extends Game 创建一个抽象类(例如 PlayerEnemyBase),它定义共享行为,然后让 Player 和 Enemy 扩展 PlayerEnemyBase。

然而,我同意 Hovercraft 的观点,即让 Player 扩展 Game 似乎有点奇怪,因为 java 中的继承旨在建模 Is-A 关系。

Yes, making an abstraction class will help, since Player and Enemy both extend the same class. Therefore you can create an abstraction class (e.g. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文