如何在接口中实现 getter/setter?

发布于 2024-12-11 19:07:11 字数 307 浏览 0 评论 0原文

我正在制作一个国际象棋游戏,并且我有一个基本的“棋子”界面,我希望所有棋子都实现该界面。我有一些公共变量,每个变量都需要有,但我不想在每个类中创建 getter 和 setter(无论如何,这似乎违背了 DRY)。

我所做的称为我的接口 PieceBase,有一个名为 Piece 的具体类,并且我有我的实际片段从 Piece 扩展并实现 PieceBase。不过,我不希望 Piece 被实例化,因为它本身没有意义,而且这种方法的某些内容让我感到不安。

这通常是如何完成的?

具体来说,这是在 Java 中,但我不知道在其他 OO 语言中是否有不同。

I'm making a chess game, and I have a base 'piece' interface that I want all the pieces to implement. I have some common variables that each need to have, but I don't want to make getters and setters in each class (seems like it goes against DRY anyway).

What I've done is called my interface PieceBase, have a concrete class called Piece, and I have my actual pieces extent from Piece and implement PieceBase. I don't want Piece to ever be instantiated though, because it doesn't make sense by itself, and something about this method makes me uneasy.

How is this normally done?

Specifically, this is in Java, but I don't know if it's different in any other OO language.

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

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

发布评论

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

评论(3

忱杏 2024-12-18 19:07:11

为了代码重用而使用继承通常被认为是不好的做法,至少在 Java 和 C++ 中是这样(有关参数,请参阅 Joshua Bloch 的“Effective Java”)。通常最好使用组合(或其他形式的委托)。

在你的情况下,我会完全扭转局面,这样 Piece 是一个 final class,只需采用一个 enum 来表示它的类型。 :

public final class Piece {

    public static enum Type {
        PAWN {
            List<Move> getLegalMoves(Color c, Location l) { /* ... */ }
        },
        BISHOP { /* ... */ },
        KNIGHT { /* ... */ },
        ROOK { /* ... */ },
        QUEEN { /* ... */ },
        KING { /* ... */ }; // i hope i didn't forget anything :P

        abstract List<Move> getLegalMoves(Color c, Location l);
        // ... etc.
    }

    private final Type type;
    private final Color color;
    private Location location;

    public Piece(Type type, Color color, Location location) {
        this.type = type;
        this.color = color;
        this.location = location;
    }

    public List<Move> getLegalMoves() {
        return type.getLegalMoves(color, location);
    }

    // ... etc.
}

因此,所有片段中通用的所有逻辑都在 Piece 中实现一次,并且不同的部分由 Type 封装。如果您需要知道正在查看的片段类型,则无需使用 instanceof 和强制转换或其他任何内容,只需实现 Piece.getType() 并对其进行 switch

It's generally considered bad practice, at least in Java and C++, to use inheritance for the purpose of code reuse (see Joshua Bloch's "Effective Java" for arguments). It's typically better to use composition (or some other form of delegation) instead.

In your case I'd turn things around entirely, such that Piece is a final class simply taking an enum representing the type of piece it is:

public final class Piece {

    public static enum Type {
        PAWN {
            List<Move> getLegalMoves(Color c, Location l) { /* ... */ }
        },
        BISHOP { /* ... */ },
        KNIGHT { /* ... */ },
        ROOK { /* ... */ },
        QUEEN { /* ... */ },
        KING { /* ... */ }; // i hope i didn't forget anything :P

        abstract List<Move> getLegalMoves(Color c, Location l);
        // ... etc.
    }

    private final Type type;
    private final Color color;
    private Location location;

    public Piece(Type type, Color color, Location location) {
        this.type = type;
        this.color = color;
        this.location = location;
    }

    public List<Move> getLegalMoves() {
        return type.getLegalMoves(color, location);
    }

    // ... etc.
}

So all of the logic common across all pieces is implemented once in Piece, and the differing portions are encapsulated by the Type. And if you ever need to know what kind of piece you're looking at, you don't need to use instanceof and cast or anything, you just implement Piece.getType() and switch on that.

蓦然回首 2024-12-18 19:07:11

您想要扩展 Piece 并实现 PieceBase 似乎很奇怪......但也许我没有看到什么。如果您使用了接口,那么所有实现它的类仍然必须定义自己的 getter/setter。

改为创建一个抽象类似乎有意义吗?

这样他们就都使用相同的 getter/setter ....如果这就是你想要实现的目标。

It seems weird that you would want to extend Piece and Implement PieceBase... but maybe I'm not seeing something. If you used an interface, all your classes that implement it will still have to define their own getters/setters.

It would seem to make sense to make an abstract class instead?

That way they all use the same getters/setters .... IF that's what you're trying to accomplish.

狠疯拽 2024-12-18 19:07:11

在这种情况下,我看不到接口的价值。我建议简单地使用所需的通用 getter 和 setter 定义抽象类 Piece,然后让您的具体类扩展 Piece。

abstract class Piece { ... common stuff ...}
class Pawn extends Piece { ... pawn-specific stuff ... }
class Knight extends Piece { ... knight-specific stuff ... }
...

In this case, I do not see the value of the interface. I suggest simply defining the abstract class Piece with the required common getters and setters and then have your concrete classes extend Piece.

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