2017-01-09 11 views
7

私はタスクを実行する必要がありますが、私は本当に立ち往生しています。入力ファイルに応じたオブジェクトの作成

基本的に、私はこのようないくつかの継承関係ました:

動物

ペットWildAnimal

鳥猫犬魚||スネークイーグル

動物はペットとワイルドの親であるが動物。 ペットは鳥、猫、犬、魚の親です。 WildAnimalはSnakeとEagleの親です。

このタスクでは、「input.txt」というファイルから入力を読み込み、Animalオブジェクトを作成したいと考えています。 「INPUT.TXT」

は次のようである:

キウイ鳥 チャーリー・イーグル マンゴー魚 唐辛子犬 角度猫 トゥイーティー鳥 ボブ犬 ジギースネーク

私は名前のすべてを取得することができますしかし私はどのような種類のオブジェクトが単一の名前を表しているかを理解する方法を理解できませんでした。ここで

はmainメソッドです:ここでは

public static void main(String[] args) throws IOException { 
    String s =""; 
    int nameCounter = 0; 
    Animal[] animals = new Animal[100]; 

    try{ 
    Scanner input = new Scanner(Paths.get("input.txt")); 

     while (input.hasNext()) { 
      s = input.next(); 
      Animal animal = new Animal(s); 
      animals[nameCounter] = animal; 
      nameCounter += 2; 
     } 
    }catch(Exception e){ 
     e.printStackTrace(); 
    } 
} 

は、動物のクラスである:

public class Animal { 
private String name; 
private int numberOfLegs; 
private int numberOfWings; 

public Animal(String name){ 
    this.name = name; 
    numberOfLegs = 4; 
    numberOfWings = 0; 
} 

public String getName() { 
    return name; 
} 
public void setName(String name) { 
    this.name = name; 
} 
public int getNumberOfLegs() { 
    return numberOfLegs; 
} 
public void setNumberOfLegs(int numberOfLegs) { 
    this.numberOfLegs = numberOfLegs; 
} 
public int getNumberOfWings() { 
    return numberOfWings; 
} 
public void setNumberOfWings(int numberOfWings) { 
    this.numberOfWings = numberOfWings; 
} 
public void talk(){ 
    System.out.printf("<Silence>"); 
} 
public void fly(){ 
    System.out.printf("%s cannot fly", getName()); 
} 
public void run(){ 
    System.out.printf("%s is running", getName()); 
} 

}

したいが、私がいない場合、私は他のすべてのクラスを追加することができますあなたがそれらを必要とすると思います。

+0

[This(http://stackoverflow.com/questions/1268817/create-new-class-from-a-variable-in-java)があなたに役立つ可能性があります。 – Blobonat

+0

すぐに受け入れてくれてありがとう! – GhostCat

答えて

4

のオブジェクトのオブジェクトをインスタンス化する必要があります。入ってくる文字列に基づいています。

例:ファイルのクラス名がBirdの場合は、何とかnew Bird()に電話する必要があります。

2つのそこに取得する方法があります:リフレクションを使用して

  1. ; switch文
  2. を使用することにより
  3. (あなたが実際には「文字列で」クラスをインスタンス化することができ、そのクラスについてを知らずに)

Reflectionは、「高度な」トピックのほうがはっきりしています(間違って使いやすいです)。私は本当にのように、オプション2のために行くことをお勧めします:

private Animal createAnimalFor(String className, String animalName) { 
    switch (className) { 
    case "Bird": return new Bird(animalName); 
    ... 
    default: throw new IllegalArgumentException("Dont know how to create object for unknown class: " + className); 
    } 
} 

(上記のコードは、「FYI」として意味する - 私は、コンパイラを介して実行しませんでした。あなたに1を与えることを意味していますアイデア)

それを超えたいくつかの注意:

  • を変更することはできません、あなたのオブジェクトのそれらの性質のために最終フィールドを使用することを検討してください。名前にセッターは必要ありません。その名前をコンストラクタのパラメータとして与えてください。言い換えれば、変更可能なフィールドを「変更可能」にするだけです。他のものは最終であるべきである。
  • 空のスロットが100個ある配列を使用する代わりに、java.util.ArrayListを使用して、そのファイルで見つけた数だけ新しい動物を追加することができます。
  • Animalクラスにequals/hashCodeメソッドを追加することをお勧めします(必須ではありませんが、がよく使われる理由は)。
  • 恐らく最も重要なことは:ではなく、これらのさまざまなメソッドをすべて基底クラスに直接配置することです。特定の関数を追加する抽象サブクラスを作成するか、特定のサブクラスが実装するinterface FlyingAnymal { void fly() };のようなインタフェースを使用するのが適切です。あなたの基底クラスに多くのメソッドを置くのは、実際には良い習慣ではありません... すべてのサブクラスのの意味を理解できません。
+0

私は反射について聞いたが、私は考えを得ることができなかった。一方、スイッチは間違いなく私が今できることです。どうもありがとう。 –

+1

Fyi:あなたのプロジェクトにいくつかのノート/一般的なヒントを追加しました。私はそれが助けて欲しい;-) – GhostCat

3

あなたは本当に(私も落胆なる)そうするためにリフレクションを使用したい場合は、ここではサンプルコードがあります:

String name = input.next(); 
String className = input.next(); 
// apply transformations to className as needed 
Class<Animal> c = (Class<Animal>) Class.forName(className); 
Constructor<Animal> constr = c.getDeclaredConstructor(String.class); // retrieves the Animal(String name) constructor 
Animal a = constr.newInstance(name); 

私は、コードは非常に複雑だとは思わないが、少数の人々が持っていますかつてはリフレクションを使用しているため、メンテナンスに問題があり、クラス定義と密接に結びついているため、おそらく多くのメンテナンスが必要になるでしょう。

+0

まあ、それは妥当と思われる。私も間違いなくこれを試してみます。 –

関連する問題