2013-11-21 54 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

相關問題