none
一つのメソッドで異なるクラスのインスタンスを返すには? RRS feed

  • 質問

  • こんばんわ

    ひであきといいます。

     

    質問の内容ですが下記の様にCreateメソッドの引数に応じて

    ある基本クラスを継承した複数のクラスのインスタンスを

    返すようなことは出来ないのでしょうか?

    ぐぐってみてFactoryパターン、COMアーキテクチャなどを

    見てみましたが違うようです。

    言語仕様的に無理なんでしょうか。

     

    Code Snippet

    public ref class Base {

      int x;

    };

     

    public ref class A : public Base {

      int a;

    };

     

    public ref class B : public Base {

      String ^b;

    };

     

    public ref class Manager {

    public:

      Base ^Create(int type);

    };

     

    Base ^Manager::Create(int type) {

      switch(type) {

        case TypeA:

          return gcnew A();

        case TypeB:

          return gcnew B();

        default:

          return nullptr;

      }

    }

    // やりたい事

    int main() {

      Manager m;

      A ^a = m.Create(TypeA);

      B ^b = m.Create(TypeB);

    }

     

     

     

    今のところ下記のアイディアしか思いつかないのですが、

    CreateXXXの羅列になってしまうのが何とかならないかと

    悩んでいます。

     

    Code Snippet

    public ref class Manager {

    public:

      A ^CreateA(void);

      B ^CreateB(void);

    };

     

     

     

    2007年9月11日 10:24

回答

  • キャストして入れればいいだけの話ではないのですか?

    A^ a = static_cast<A^>(m.Create(TypeA));

    2007年9月11日 12:14
  • ものすごく蛇足な回答かもしれません。

     

     ひであき さんからの引用

    // やりたい事

    int main() {

      Manager m;

      A ^a = m.Create(TypeA);

      B ^b = m.Create(TypeB);

    }

     

    これを

    int main() {

      Manager m;

      Base ^a = m.Create(TypeA);

      Base ^b = m.Create(TypeB);

    }

    として使えるようにBaseを設計するという方向もあると思います。

     

    ※それができない事情があるから今回の質問をされていると思いますが。

    2007年9月11日 12:48
  • おはようございます。

     

    ご指摘のとおり

    http://forums.microsoft.com/msdn-ja/ShowPost.aspx?PostID=1541979&SiteID=7

    を引きずっています。

     

    私が考えていることができるなら、例えば.Net FrameworkでObjectを

    継承している全てのクラスが一つのメソッドで生成できることになり

    ますよね。

    色々考えましたがキャストして使うのが一番良いような

    気がしてきました。

     

    2007年9月12日 1:48

すべての返信

  • キャストして入れればいいだけの話ではないのですか?

    A^ a = static_cast<A^>(m.Create(TypeA));

    2007年9月11日 12:14
  • ものすごく蛇足な回答かもしれません。

     

     ひであき さんからの引用

    // やりたい事

    int main() {

      Manager m;

      A ^a = m.Create(TypeA);

      B ^b = m.Create(TypeB);

    }

     

    これを

    int main() {

      Manager m;

      Base ^a = m.Create(TypeA);

      Base ^b = m.Create(TypeB);

    }

    として使えるようにBaseを設計するという方向もあると思います。

     

    ※それができない事情があるから今回の質問をされていると思いますが。

    2007年9月11日 12:48
  • ありがとうございます、おっしゃるとおりです。

    A^ a = dynamic_cast<A ^>(m.Create(TypeA));

    は、考えてみました。
    情報を小出しにしてすいません。
    ただ、これだと結局Createメソッドを使用時にそれぞれの型情報を記述する
    必要があるので、同じ数のCreateXXを用意するのと手間が同じかなと
    思い、できれば他に解決方法がないかと考えていました。
    2007年9月11日 13:39
  • すみません、具体的にどう設計すればよいのでしょうか?

    クラスAとクラスB固有のメンバ変数やメソッドといった作り方が
    できないと思うのですが?
    2007年9月11日 13:41
  • 私がイメージしているのはストラテジー(Strategy)パターンです。

    クラスAとクラスBの固有処理がどれくらい違うのかが分からないので

    具体的なコードを示せないのがつらい所ですね。

     

    上位から本当に固有のメソッドを呼ぶ必要があるかどうかが判断基準になると思います。

    2007年9月11日 14:16
  • ありがとうございます。

    早速ストラテジーパターンを調べてみます。

     

    あと、代替案で以下を考えてみましたが

    mainのA ^aが未定義でこけてしまいました。

     

    Code Snippet

    public ref class Manager {
    public:
     void Create(int type, Base ^%obj);
    };

     

    void Manager::Create(int type, Base ^%obj) {
     switch(type) {
      case 0:
       obj = dynamic_cast<A ^>(gcnew A());
       break;
      case 1:
       obj = dynamic_cast<B ^>(gcnew B());
       break;
      default:
       obj = nullptr;
     }
    }

     

    int main(array<System::String ^> ^args)
    {
     Manager m;
     A ^a;
     m.Create(0, a);

    }

     

    2007年9月11日 14:54
  •  ひであき さんからの引用
    ありがとうございます、おっしゃるとおりです。

    A^ a = dynamic_cast<A ^>(m.Create(TypeA));

    は、考えてみました。
    情報を小出しにしてすいません。
    ただ、これだと結局Createメソッドを使用時にそれぞれの型情報を記述する
    必要があるので、同じ数のCreateXXを用意するのと手間が同じかなと
    思い、できれば他に解決方法がないかと考えていました。

     

     ひであき さんからの引用

     

    Code Snippet

    // やりたい事

    int main() {

      Manager m;

      A ^a = m.Create(TypeA);

      B ^b = m.Create(TypeB);

    }

     

    ちょっと不思議なのですが,この「やりたいこと」だと結局左辺にそれぞれの型情報 (AとかBとか) を書いてますよね?

    これは手間じゃないのでしょうか?

    一回だけAと書くのが手間じゃないのなら,templateやマクロで一回だけ書く記法を自分で作ったら良いような気がしますが.

     

    あともしかして

    http://forums.microsoft.com/msdn-ja/ShowPost.aspx?PostID=1541979&SiteID=7

    の続きですか?

    2007年9月12日 1:23
  • おはようございます。

     

    ご指摘のとおり

    http://forums.microsoft.com/msdn-ja/ShowPost.aspx?PostID=1541979&SiteID=7

    を引きずっています。

     

    私が考えていることができるなら、例えば.Net FrameworkでObjectを

    継承している全てのクラスが一つのメソッドで生成できることになり

    ますよね。

    色々考えましたがキャストして使うのが一番良いような

    気がしてきました。

     

    2007年9月12日 1:48