2013-12-24 3 views
0

Здравствуйте, я новичок в объектно-ориентированном программировании. У меня есть книга от друга Роджерса Каденхеда (Java в 21 день), и я стараюсь как можно больше зайти на этот языкПеременная объекта в суперклассе, которая относится к подклассу

Я знаком с языком C, но у меня проблемы с мышлением на Java, так что я прошу, возможно, не лучший способ сделать то, что я хочу. Любые советы, чтобы сделать это по-другому, приветствуются.

Мой вопрос немного общий и должен делать больше с моделированием и меньше с кодом записи.

Я пытаюсь построить шахматную программу (не полностью работоспособную), чтобы работать с разными объектами, интерфейсами e.t.c, чтобы привыкнуть к мышлению.

У меня есть 2 класса и 1 интерфейс на данный момент все в одном пакете. Я собираюсь писать классы для каждой части шахмат (ладьи, Knight, и т.д.), который будет распространяться фишки класса (который является общим шахматной фигурой класса .... суперкласс) Классами я к настоящему времени являются:

  • ChessMovesList.java: Этот класс в основном LinkedList из точки с некоторыми методами оных, получить и т.д. Я использую его, чтобы сохранить правильные ходы куске каждый раз.
  • ChessBehaviour.java: Это интерфейс. Он имеет такие методы, как: public abstract ChessMovesList getValidMoves(); публичный аннотация boolean makeMove (точка p); Я реализую его в каждом классе штук (Rook, Knight и т. Д.), И я напишу методы для каждой части в своем классе
  • ChessPiece.java: Это будет Суперкласс каждого класса штук (Rook, Knight и т. Д.) Он содержит переменные, такие как цвет или положение каждой части.

Теперь вопрос:

Я хочу, чтобы добавить переменную в фишку держать тип части. Сначала я подумал о добавлении персонажа, такого как «r» для ладьи, «k» для рыцаря и т. Д. Выполнил бы эту работу, но тогда я подумал, что хочу типа, который будет чем-то вроде Объект. Я хочу, чтобы тип был Rook, или Рыцарь, а не какой-либо символ 'r', или 'k'. Это может быть доступно для записи в виде кода, но я не знаю, может ли его сделать ссылку подклассу суперкласса, особенно когда я собираюсь создать подкласс (пример: новый Rook();). Я хочу, например, два разных объекта Rook для того же типа и не разные , потому что их ссылки разные.

В основном у меня возникают проблемы с моделированием того, что я хочу написать, а не писать.

Причина, по которой я хочу сохранить тип предмета в ChessPiece класс - это потому, что я хочу написать некоторые методы, которые позволят получить объект Rook, Knight. Поэтому я буду использовать литье типа на Rook, или Knight и т. Д., И я буду иметь информацию о типе детали после отливки.

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

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

Заранее спасибо

Это код, который я на курсе (его не завершен, потому что им застрял).

ChessMovesList.java пакет шахмат;

import java.awt.Point; 
import java.util.LinkedList; 

public class ChessMovesList { 
    private LinkedList<Point> movesList; 

    public ChessMovesList() { 
     movesList = new LinkedList<Point>(); 
    } 

    public void addMove(Point p) 
    { 
     if ((p.x >= 0) && (p.x <= 7) && (p.y >= 0) && (p.y <= 7)) 
      movesList.add(p); 
    } 

    public LinkedList<Point> getMovesList() 
    { 
     return movesList; 
    } 

    public int getMovesNum() 
    { 
     return movesList.size(); 
    } 


} 

ChessBehaviour.java

package chess; 

import java.awt.Point; 

public interface ChessBehaviour { 
    public abstract ChessMovesList getValidMoves(); 
    public abstract boolean makeMove(Point p); 
} 

ChessPiece.java пакет шахматы;

import java.awt.Color; 
import java.awt.Point; 

public class ChessPiece { 
    private Color color; 
    private Point position; 
} 
+6

Это имеет код запах для меня. Родительский класс не должен знать своих детей. Никто. –

+0

Зачем шахматной доске знать, какой тип на самом деле? Что он будет делать с этой информацией? – Vadim

+0

C1: Родитель, зная его ребенок, тоже пахнет. Вот почему я говорю, что я думаю, неправильно. C2: Я хочу сделать один метод, который получит объект ChessPiece, вместо того, чтобы сделать больше метоз, будет перегружен и получит объект Rook, объект Knight и т. Д. C3: Я тоже думал об этом, но myChessPiece - это переменная объекта , Как передать эту переменную методу?Я хочу, чтобы один и тот же метод обрабатывал как объект Rook, так и объект Knight, поэтому я думал, что передам их, указав его на свой суперкласс (вот почему мне нужен тип в суперклассе, поэтому я не потеряю информацию об этой части) – tchar

ответ

0

Это очень выполнимое и обычное дело, я действительно не совсем понимаю вашу проблему.

Вы должны посмотреть, как сделать класс ChessPiece абстрактным, вы никогда не хотели его инициировать.

Это не проблема для ChessPiece, чтобы иметь ChessType в качестве участника. Я хотел бы также определить поглотитель в фишку:

public ChessType getChessType() {return chessType;} 

Access Subclasess этот элемент, используя сорбент, а затем непосредственно.

Будучи, что вы только начинаете, я бы параметризированный конструктор для фишки, например, только этот конструктор:

public ChessPiece(ChessType chessType) { 
    this.chessType = chessType; 
} 

Затем конструктор класса ладьи будет выглядеть примерно так:

public Rook() { 
    super(new ChessType("rook")); 
    .... 
} 

Для людей, знакомых с концепцией, это легче выполнять с помощью заводских методов, но, надеюсь, это даст вам представление о том, как начать.

0

Вам не нужно вручную вести запись о том, какой тип ChessPiece есть. Java уже предоставляет кучу методов, которые позволяют вам выяснить, какой тип объекта есть.Например

ChessPiece myChessPiece = new Rook(); 
... 

// evaluates to true 
if (myChessPiece instanceof Rook) { ... } 

// evaluates to false 
if (myChessPiece instanceof Pawn) { ... } 

// evaluates to true 
if (myChessPiece.getClass().equals(Rook.class)) { ... } 

// evaluates to true 
if (Rook.class.isAssignableFrom(myChessPiece.getClass())) { ... } 

// also evaluates to true 
if (ChessPiece.class.isAssignableFrom(myChessPiece.getClass())) { ... } 

// evaluates to false since myChassPiece's type Rook isn't equal to or a superclass of ChessPiece (it's a subclass) 
if (myChessPiece.getClass().isAssignableFrom(ChessPiece.class)) { ... } 

Что касается присвоения имени ваших шахматных фигур, вы можете просто использовать

// this will be the name of the class which is just "Rook" 
myChessPiece.getClass().getSimpleName() 

или добавить метод getName() в ChessPiece и имеете реализующие классы реализуют этот метод, чтобы вернуть свое имя. В противном случае вы можете иметь ChessPiece класс реализовать метод getName(), но есть подклассы обеспечивают значение, метод будет возвращать во время строительства, как это:

public abstract class ChessPiece { 
    private final String name; 
    ...  
    protected ChessPiece(String name) { 
    this.name = name; 
    } 
    ... 
} 

public final class Rook extends ChessPiece { 
    ... 
    public Rook() { 
    super("I am a Rook"); 
    } 
    ... 
} 

Что касается коды, публикуемой у меня есть несколько замечаний:

1) В вашем ChessMovesList.getMovesList() вы возвращаете прямую ссылку на movesList, поэтому, если пользователь вносит изменения в возвращенный список, тогда будет изменен movesList, хранящийся на вашем ChessMovesList. Для защиты от этого вы можете вместо того, чтобы возвращать либо

Collections.unmodifiableList(movesList); 

// or 
new ArrayList<Point>(movesList); 

2) В интерфейсе ChessBehaviour вы объявляете методы, как public abstract, однако это уже автоматическая для интерфейса, так что вы можете опустить их.

3) Ваш ChessPiece обычный класс, однако это не имеет особого смысла иметь сырые ChessPiece объекты в шахматной игре (все они пешки, ладьи, рыцари и т.д.), так что я хотел бы сделать этот класс abstract к что он не может быть создан.

4) Ваш ChessPiece содержит объект Color, чтобы обозначить его цвет. В шахматах могут быть только два цвета, поэтому я бы использовал enum с двумя значениями, такими как другой ответ, предлагаемый вместо этого сохранить цвет.

1

Всякий раз, когда вы чувствуете желание хранить тип объекта, который вы действительно используете, или запускайте gettype на себя, чтобы решить, что делать - вы должны думать только об одном: Полиморфизм.

От вас комментарий - «Вариант номер один - сделать общедоступным void doSmth (ладья ладьи), public void doSmth (рыцарь-рыцарь) и т. Д. Другой вариант - написать один метод public void doSmth (ChessPiece cp), поддерживающий тип в родительском классе позволит мне написать один метод вместо 5 методов для простой вещи »

Нет, есть третий вариант - сделайте абстракцию doSmth в суперклассе и реализуйте его по-разному в каждом производном классе. Поскольку методы виртуальны в Java, правильный метод будет корректно работать для каждого экземпляра.

(я не обращался к остальной части вашего дизайна, потому что я предпочитаю, чтобы ответить на конкретные вопросы)

Смежные вопросы