2013-11-21 51 views
0

所以,这可能是也可能不是你想象的,我并不完全确定我已经正确地解决了这个问题,但是我们开始吧!我正在制作一款国际象棋游戏,我正试图通过如何称呼我的课程,制作作品以及将它们放在电路板上来充满活力。使用一个变量来调用一个新类的实例

运行在代码上:我读取了一个文件,其中包含诸如“pla1”之类的代表片段,颜色,x坐标和y坐标的文件。在本例中,板上的p = pawn,l = white,a = x坐标,1 =板上的y坐标。所以:

“白色的棋子是A1”

简单。现在,我有一个能够从文件中解析文件的小块类,并且有一个名为“典当”的特定类,所以当我想为板添加一块时,该块有自己的类来管理它的移动能力和权力棋盘等。

问题:我不知道如何动态设置我的作品类。我可以使用硬编码版本轻松完成此操作,就像您在注释中看到的或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"); 

     } 
} 

我不知道这是可以做到的。任何帮助将不胜感激,如果需要对代码进行详细说明,我可以提供。

+0

你说的“硬编码”好像是某种邪恶......而“动态地做这个或那个”似乎是某种最佳实践。 Java是一种静态类型的语言。如果您试图设计出无视这一事实的解决方案,那么您正在努力尝试,并且最终会导致代码错误。国际象棋游戏充满了静态类型的数据(这些片段在编译时都是已知的)。我发现你坚持认为你必须“动态地”这样做(这样你就没有利用conpile时间类型检查和安全性)是荒谬的。 – scottb

+0

呃,它只是我发现有用的东西,它是OOP的一个重要组成部分,能够动态地完成它。我宁愿用动态的方式来缩短我的代码。 – user2453973

+0

然后,不同的语言会更好地满足您的需求。 Java中的反射代码很慢。阅读和阅读也非常冗长和丑陋。而且,在包含所有异常处理的时候,您的代码几乎总是更长更冗长。当存在静态类型的解决方案时,避免Java中的反射代码为您提供卓越的安全性,更高的类型安全性,卓越的稳健性和可维护性以及更高的性能。使用静态类型的环境的优点是令人信服的。 – scottb

回答

0

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

从中直接引用:

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

  1. Class.newInstance()只能调用无参数构造, 而Constructor.newInstance()可调用任何构造,而不管 参数数量。
  2. Class.newInstance()抛出构造函数抛出的任何异常 ,不管它是否被选中,或者 未被选中。 Constructor.newInstance()始终使用InvocationTargetException封装抛出的异常 。
  3. Class.newInstance()要求 的构造函数是可见的;在某些情况下,Constructor.newInstance()可能会调用 私有构造函数。

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

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; 
    } 

既然你也标注了国际象棋标签的问题,我建议立即进行删除d指出你应该使用标准Forsyth-Edwards Notation填充棋盘。它使用大写字母来表示白色部分和小写字母来表示黑色部分。

+0

感谢您指点我正确的方向。仍然搞乱它,但它可以这样做。 – user2453973

+0

我已经用更完整的代码更新了答案。 – Chandranshu

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); 
    } 
} 
+0

OP不想使用Ifs – Chandranshu

+0

他可以使用反射(如果他愿意,可以使用'Constructor.newInstance()'),但是工厂类是从主代码中移除硬编码并分离文件解析和对象创建的好方法。 –

+0

是的,是的。但上面的代码不会删除任何硬编码! – Chandranshu

相关问题