Как вы реализуете геттеры / сеттеры в интерфейсе? - PullRequest
0 голосов
/ 26 октября 2011

Я делаю шахматную игру, и у меня есть базовый интерфейс «штук», который я хочу реализовать всеми фигурами. У меня есть некоторые общие переменные, которые должны быть у каждой, но я не хочу, чтобы в каждом классе были методы получения и установки (кажется, что в любом случае это идет вразрез с DRY).

То, что я сделал, называется моим интерфейсом PieceBase, у меня есть конкретный класс Piece, и у меня есть фактический экстент кусков из Piece и реализация PieceBase. Я не хочу, чтобы Piece когда-либо создавался, потому что он сам по себе не имеет смысла, и что-то в этом методе вызывает у меня беспокойство.

Как это обычно делается?

В частности, это на Java, но я не знаю, отличается ли это на любом другом языке OO.

Ответы [ 3 ]

2 голосов
/ 26 октября 2011

Обычно считается плохой практикой, по крайней мере в Java и C ++, использовать наследование для повторного использования кода (см. «Эффективная 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 для этого.

1 голос
/ 26 октября 2011

Кажется странным, что вы захотите расширить Piece и Implement PieceBase ... но, возможно, я чего-то не вижу. Если вы использовали интерфейс, все ваши классы, которые его реализуют, все равно должны будут определять свои собственные методы получения / установки.

Казалось бы, имеет смысл вместо этого создать абстрактный класс?

Таким образом, все они используют одни и те же геттеры / сеттеры .... ЕСЛИ это то, что вы пытаетесь достичь.

0 голосов
/ 26 октября 2011

В этом случае я не вижу значения интерфейса. Я предлагаю просто определить абстрактный класс Piece с помощью необходимых общих методов получения и установки, а затем попросить ваши конкретные классы расширить Piece.

abstract class Piece { ... common stuff ...}
class Pawn extends Piece { ... pawn-specific stuff ... }
class Knight extends Piece { ... knight-specific stuff ... }
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...