dq37281757
@dq37281757 (dq37281757)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

新しくインスタンスをnewする方法

Q&A

Closed

状況

道具(Itemクラス)を継承した鉛筆(Pencilクラス)、消しゴム(Eraserクラス)、定規(Rulerクラス)があり、道具の不良品を回収して同じ型の製品を新しく生成してくれる機械(Machine)クラスがあるとします。機械はメソッドreproduct(Item i)で道具を再生成できます。

コード

public abstract class Item{
}
public class Pencil extends Item{
}
public class Eraser extends Item{
}
public class Ruler extends Item{
}
public class Machine{
    public Item reproduct(Item i){
        //同じ型だがiとは異なるItemをnewしたい
        return ??;
    }
}

解決したいこと

将来的に道具が100種類くらいになった時に、道具ごとにreturn new Pencil();などと書くのは大変です。インスタンスを新しく生成するのに何か簡単に書く方法はありますか?

0

1Answer

mainメソッドから呼んでいるのでstaticついてますが一応こんな感じでいけます。

public static void main(String[] args) {
  Item p = new Pencil();
  Item copy = new Machine().copy(p);
  System.out.println(copy.getClass().getSimpleName());
}

public static abstract class Item {
  abstract Item copy();
}

public static class Pencil extends Item {
  Pencil copy() {
    return new Pencil();
  }
}

public static class Eraser extends Item {
  Eraser copy() {
    return new Eraser();
  }
}

public static class Ruler extends Item {
  Ruler copy() {
    return new Ruler();
  }
}

public static class Machine {
  public Item reproduct(Item i) {
    return i.copy();
  }
}
  1. Itemクラスに抽象メソッドとして、インスタンスを新規で作成するメソッドを追加する
  2. 各クラスで上記のメソッドの実装を行う

このへんも書きたくないとなると、リフレクションというものを使う他ないと思います。

Pencil copy() {
  return new Pencil();
}

リフレクションを使ったサンプル

public static void main(String[] args) throws Exception {
  Item p = new Pencil();
  Item copy = new Machine().copy(p);
  System.out.println(copy.getClass().getSimpleName());
}

public static abstract class Item {
}

public static class Pencil extends Item {
}

public static class Eraser extends Item {
}

public static class Ruler extends Item {
}

public static class Machine {
  public Item reproduct(Item i) throws Exception {
    return i.getClass().getDeclaredConstructor().newInstance();
  }
}

ただし、リフレクションはどこから何が呼ばれているのかわかりにくくなるため、あまり使わないほうが良いです。

1Like

Comments

  1. @dq37281757

    Questioner

    分かりやすい解答ありがとうございます。抽象メソッドを実装する方を試してみます。リフレクションは初めて知りましたが、こちらも試してみようと思います。

Your answer might help someone💌