2017-03-18 17 views
2

コンピュータカードゲーム(Hearthstoneのようなものですが、あまり複雑ではありません)を開発しようとしています。私はゲームに必要なすべてのカードをデータベースに持っています。 テーブルには、カードタイプを格納するカラムcardTypeがあります。これは、Javaオブジェクトの対応するコンストラクタである必要があります。テーブルフィールドに基づいてそのタイプのオブジェクトをインスタンス化する必要があります。Javaリフレクションを使用したトレーディングカードゲームでのカードとエフェクトの実装

例: 私のテーブルにはcardType = BasicMinion(7,7)のカードがあります。

は、次にJavaで私はクラスを持っている:

BasicMinion extends Card { 
public BasicMinion(int health, int attack) { 
// initialize 
} 
public void play(){ 
//do something 
} 
} 

私はこのような何かをやって、データベースから取得した文字列を使用してオブジェクトを作成するためにリフレクションを使用することができます。 Java how to instantiate a class from string

しかし、私のカードを反応することができるいくつかの基本事象を有するクラスCardを拡張する。リフレクションでは、基底クラスCardのメソッドと、派生クラスのメソッドを呼び出すことができますか?

基本的に私はArrayList<Card>を持っています。データベースから取得したすべてのカードタイプを置くことができるので、イベントが発生したときにメソッドを呼び出すことができます。

何か不足しているようです。質問はかなり曖昧ですが、どうすればいいですか?

+0

ので、あなたが作成した後のオブジェクトのこれらのメソッドを呼び出すことができます。私は、なぜあなたが既にBasicMinionを持っているので、あなたがCardメソッドを呼び出すためにリフレクションを必要とするのかよく分かりません。 –

+0

計画があるようです。データベースに 'class'の名前だけでなく、コンストラクタの引数とその値の型も格納します。それをどうやって行うのがあなたの練習です。次に、リフレクションを使用して、 'MyCard'のインスタンスを' Card'として作成し、 'Card'インタフェースを介してメソッドを呼び出します。問題は何ですか? –

答えて

0

ここでリフレクションを使用して、クラスの新しいインスタンスを作成します。

これを実行した後は、初めに作成したのと同じ「同じ」通常のオブジェクトがあります。

つまり、リフレクションを使用してオブジェクトをリフレクションで再作成することはできますが、リフレクションを使用する必要はありません。

最後に、instanceofとcastを使用すると、サブクラス固有のメソッドを呼び出すことさえできます。さて、あなたはになりますそうすることができます - しかし、ダウンキャストはしばしば悪いデザインの匂いです。だから、あなたがベースのCardクラスによって提供されるメソッドに満足しているときは、すべてがより良い。

+0

例えば、 'ArrayList 'を持っていれば、この配列のリフレクションを使用して取得したオブジェクトを追加することができます。その後、 'Card'クラスのメソッドを呼び出すことができますか? – Andy

+0

はい、一度作成すると通常の「カード」オブジェクトなので、ArrayListに追加できます。また、反射を全く使わずに私の答えを探してください。 –

+0

今、1時間前に私が見たアップヴォートを取ったのは、皆さんのうちに本当に興味があります。特に私たちが良い建設的な議論をしているという事実を考えてみると、... – GhostCat

1

私のカードは、 が反応できるいくつかの基本的なイベントを持つクラスのカードを拡張します。リフレクションは私がベースの クラスのカードからメソッドを呼び出すことができますか?また、派生クラスにはメソッドがありますか?

あなたは(以下に示すようにClass.forName()newInstance()方法を使用してのような)文字列を使用して、クラスのオブジェクトを作成するとはい、は、参照を使用して、基本クラスCard及びサブクラスBasicMinionのメソッドを呼び出すことができます。

Class card = Class.forName("com.myproject.Card"); 
Card cardObj = (Card)card.newInstance(); 
//invoke cardObj.method1(); 

Class basicMinion = Class.forName("com.myproject.BasicMinion"); 
BasicMinion basicMinionObj = (BasicMinion)basicMinion.newInstance(); 
//invoke basicMinionObj.method1(); 
+0

データベースから文字列を取得した後にタイプを見つけるだけで、特定のカードにキャストを行うにはどうすればいいですか?私はそれがBasicMinionであるかどうかわからないのです。 – Andy

+0

あなたはキャストするためにタイプを知る必要があります。だから、もう一度switch()が必要です。反射を役に立たないようにする:-) –

1

あなたは(あなたが最も可能性が高いしません)さまざまなカードタイプを持っていない場合は、代わりに、工場(私が知っている、Javaや工場)を使用することができます。 より明確なコードと優れた例外処理オプションが可能になります。

例:BasicMinionは、カードを拡張

public Card createCard(String definition) { 
    String type = //do parsing of definition (string splitting etc) 
    String parameters = //do parsing of definition 

    switch(type) { 
     case "BasicMinion": 
      Long param1 = ///do parsing of parameters 
      Long param2 = ///do parsing of parameters; 
      return new BasicMinion(param1, param2); 
     //add others.. 
     default: throw new UnknownCardTypeException(); 
    } 
} 
+0

私はこれをこのようにすることを考えました。しかし、新しいカードタイプが追加されるとどうなりますか?スイッチに別のケースを追加するだけですか? – Andy

+0

新しいCardサブクラスを作成したので、とにかくアプリケーションを再コンパイルする必要があります。 "default:throw new UnknownCardTypeException();"テスト中に例外がスローされるため、このクラスに何も追加せずに新しいカードタイプを追加することはできません。 –

+0

反射はクールでいい考えですが、非常に壊れやすいです。私はあなたが持っているカードの種類とそれらがどのように構築されているかを非常に明確にしているので、上記の方法を好む。反射エラー処理は混乱です。 –

関連する問題