使用变量来调用类的新实例

时间:2013-11-21 06:25:51

标签: java chess

所以,这可能是也可能不是你的想法,我不完全确定我已经正确地提出了这个问题,但是我们走了!我正在建立一个国际象棋游戏,我正在尝试动态我如何调用我的类,构建片段,并将它们设置在板上。

向下看代码:我读了一个包含诸如“pla1”之类的文件的文件,表示一个部分,它的颜色,它的x坐标和它的y坐标。在这个例子中,p = pawn,l = white,a =板上的x坐标,1 =板上的y坐标。这样:

“白色棋子在a1”

简单。现在,我有一个片段类来解析文件中的片段,以及一个名为“Pawn”的特定类,所以当我想要向棋盘添加一个片段时,该片段有自己的类来控制它的移动能力和开启功能国际象棋棋盘等。

问题:我无法弄清楚如何动态设置我的作品类。我可以使用硬编码版本轻松完成此操作,您可以在评论中看到,或者使用if声明。是否可以使用我的字符串变量设置我的类?

我的代码如下:

//reads from the file, puts each line into an arraylist
public void readFromFile(String fileName) throws IOException 
{
    String line;
    BufferedReader br = new BufferedReader(new FileReader(fileName));

    //adds line to arraylist    
    while((line = br.readLine()) != null) 
       fileLines.add(line.toLowerCase());

    //send each line in the list to method
    for(String item : fileLines) 
        buildPiecesFromFileAndGetLocation(item);
} 

ChessPiece[][] pieces = new ChessPiece[9][9]; my chessboard
String spawnPiece;
String spawnColor;
String pieceRepresentation;

String originx;
int originX;
int originY;


public void buildPiecesFromFileAndGetLocation(String item)
{
    //regex matcher // using this to match it: Pattern copyPiece = Pattern.compile("(?<piece>q|k|b|p|n|r+)(?<color>l|d)(?<x>\\w)(?<y>\\d)");
    Matcher copyMatcher = copyPiece.matcher(item);

    //hashmap for matching quicker; currently only has pieceMatches.put("p", "Pawn") within it      
    hashIdentities();

    if (copyMatcher.find())
    {

        spawnPiece = pieceMatches.get(copyMatcher.group("piece")); //spawnPiece becomes "Pawn"
        spawnColor = colorMatches.get(copyMatcher.group("color"));
        pieceRepresentation = spawnPiece + spawnColor;

        originx = copyMatcher.group("x"); //change letter to number 
        transferChars(); //changes letter "a" into integer "1"
        originY = Integer.parseInt(copyMatcher.group("y")); //string to int

        //PROBLEM:
        pieces[originX][originY] = new spawnPiece(pieceRepresentation); //since spawnPiece is now "Pawn" i want it to be able to call a new instance of the class Pawn. this way doesn't work. Solution?

        //logic:
        //pieces[a][b] = new (WHATEVER PIECE WAS MATCHED)("position + color");

        //hardcoded version:
        //pieces[1][1] = new Pawn("PawnWhite");

      }
}

我不确定这是否可行。任何帮助将不胜感激,如果需要任何详细的代码我可以提供。

2 个答案:

答案 0 :(得分:2)

使用工厂类。

interface ChessPieceFactory {
  ChessPiece create(String pieceName);
}

class ChessPieceFactoryImpl {
  public ChessPiece create(String pieceName) {
    if("pawn".equals(pieceName))
      return new Pawn(pieceName);
    throw new IllegalArgumentException(pieceName);
  }
}

答案 1 :(得分:0)

看看这篇文章:http://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html

直接引用它:

  

有两种用于创建类实例的反射方法:   java.lang.reflect.Constructor.newInstance()和Class.newInstance()。   前者是优选的,因此在这些例子中使用,因为:

     
      
  1. Class.newInstance()只能调用零参数构造函数,   而Constructor.newInstance()可以调用任何构造函数,无论如何   参数数量。
  2.   
  3. Class.newInstance()抛出任何异常   由构造函数抛出,无论是否被检查或   选中。 Constructor.newInstance()始终包装抛出的异常   使用InvocationTargetException。
  4.   
  5. Class.newInstance()需要   构造函数是可见的; Constructor.newInstance()可以调用   私人施工人员在某些情况下。
  6.   

让我为你添加一些代码。首先,您需要获取要创建其实例的类的引用。您已经拥有该类的名称,所以这样做:

Class pieceKlass = Class.forName(spawnPiece)

然后获取其构造函数,该构造函数接受单个字符串并创建该类的实例:

Constructor ctor = pieceKlass.getDeclaredConstructor(String.class);
ctor.setAccessible(true);
ChessPiece piece = (ChessPiece)ctor.newInstance(pieceRepresentation);

鉴于这段代码非常复杂并且需要一些错误处理,您现在可以整齐地在工厂类中提取它:

class ChessPieceFactory {
    public ChessPiece create(String pieceName, String pieceRepresentation) {
      ChessPiece piece;
      try {
        Class pieceKlass = Class.forName(pieceName)
        Constructor ctor = pieceKlass.getDeclaredConstructor(String.class);
        ctor.setAccessible(true);
        piece = (ChessPiece)ctor.newInstance(pieceRepresentation);
       // production code should handle these exceptions more gracefully
     } catch (ClassNotFoundException x) {
        x.printStackTrace();
     } catch (InstantiationException x) {
        x.printStackTrace();
     } catch (IllegalAccessException x) {
        x.printStackTrace();
     } catch (InvocationTargetException x) {
        x.printStackTrace();
     } catch (NoSuchMethodException x) {
        x.printStackTrace();
     }

     return piece;
  }

由于您还使用Chess标记标记了问题,我应该指出您应该使用标准Forsyth-Edwards Notation来填充国际象棋棋盘。它使用大写字母表示白色字母,小写字母表示黑色字母。