2016-02-15 4 views
0

Я пишу программу Java для игры в шахматы с множеством разных классов. Так, например, у меня есть Chess_Piece суперкласса, и от этого у меня много подклассов, как Rook, King и т.д.,Как вызвать методы подкласса из объекта суперкласса

У меня есть метод isValidMove() в каждом подклассе (как каждая часть двигается определенным образом). Есть ли способ позвонить isValidMove() на объект Chess_Piece, где компилятор позаботится о том, какой конкретный подкласс isValidMove() позвонить?

По существу, я беру данные от пользователя, а затем перемещаю Chess_Piece в этом месте. Моя программа не может точно определить, какой подкласс Piece находится в этом месте без сложной системы ifs (то есть if Chess_Piece.toString=="Rook", if Chess_Piece.toString=="Bishop" и т. Д.). Есть идеи?

+1

Это просто звучит как прямое наследование.Определите метод в суперклассе, переопределите его в подклассах. –

+0

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

ответ

1

Это поведение по умолчанию для Java (и для любого нормального языка OO).

У вас есть код, который не ведет себя так?

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

public class ChessPiece { 
    public void isValidMove(){ 
     System.out.println("Super"); 
    } 
} 

public class King extends ChessPiece { 
    public void isValidMove(){ 
     System.out.println("King"); 
    } 
} 

public class Queen extends ChessPiece { 
    public void isValidMove(){ 
     System.out.println("Queen"); 
    } 
} 

если вы проверить это с какой-то код, который вы увидите Java ведет себя так, как вы хотите уже:

public static void main(String[] args) { 
    ChessPiece king = new King(); 
    //king is declared to be a ChessPiece, but the value is a king. 
    king.isValidMove(); 
} 

Какие производит: King

подробнее о такого рода поведении здесь: https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html https://en.wikipedia.org/wiki/Polymorphism_(computer_science)

2

Это именно то, о чем идет полиморфизм.

// The whole class must be declared abstract if it contains at least one abstract method. 
// Abstract classes themselves can't be instantiated, but their non-abstract subclasses can be. 
public abstract class Chess_Piece { 

    // Declare the method as abstract. 
    // "Abstract" means that the implementation will be provided in subclasses. 
    // Make it protected if not called from outside this class hierarchy. 
    // Declare arguments as needed. 
    public abstract boolean isValidMove(); 

    // Your other methods. 
    // You may call `isValidMove()` in other methods. 

} 

// King class provides implementation of all abstract methods, 
// and therefore the class isn't abstract. 
public class King extends Chess_Piece { 

    @Override 
    public boolean isValidMove() { 
     // Implement method body as needed 
     return true; 
    } 

} 
+0

Я думал об этом, но я считаю, что это немного сложнее. Когда я получаю ввод пользователя, я не знаю, какой тип Chess_Piece находится в этой конкретной позиции. Поэтому мне нужно создать экземпляр объекта, который может быть любым из подклассов, но, очевидно, вы не можете создать экземпляр абстрактного класса. Есть идеи? – will3321

+0

@ will3321 элемент, занимающий эту позицию, должен быть уже создан. Он должен был быть создан в начале игры. –

+1

will3321: что сказал ErickG.Hagstrom, и если экземпляр куска не знает его текущего положения, тогда определите текущую позицию как параметр метода IsValidMove и передайте правильную позицию, когда вы ее вызываете. –

0

Ну, попробуйте это ... Вы говорите, что Chess_Piece piece вводится пользователем, так

if(piece instanceof Pawn){ 
// do Pawn thing 
} 
else if(piece instanceof Rook){ 
//do Rook thing 
} 
//and for all 

Но я рекомендую вам использовать понятие полиморфизма, как указано в других ответах.

полиморфизм, вы можете написать

piece.isValidMove(); 

и она отлично работает для всех.

1

При вызове функции на объекте она будет выглядеть сначала в классе, который создал объект, затем в его суперклассе и т. Д. По дереву наследования. Поэтому, если вы вызываете Chess_Piece piece = new Rook(), тогда piece.isValidMove() вызовет метод isValidMove класса Rook.

В вашем случае использования я бы рекомендовал объявить абстрактную функцию в Chess_Piece:

public class Chess_Piece { 
    public abstract boolean isValidMove(); 
} 

Таким образом, вы гарантируете, каждый класс, который расширяет Chess_Piece имеет метод isValidMove() или он не будет компилировать.

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