どのように(実行時に)自分の関数から返すタイプを決定できますか?
これはまったく可能ですか?
私はそうだとは思いますが、決して確実なことはありません。異なるタイプの返却
答えて
使用多型
public interface MyType {
public void doSomething();
}
public class A implements MyType {
public void doSomething(){}
}
public class B implements MyType {
public void doSomething(){}
}
public class MyClass {
public MyType getData(){
if (/* some condition */){ return new A(); }
return new B();
}
public void test(){
MyType o = this.getData();
o.doSomething();
}
}
単にMyType
の種類を返すと、そのオブジェクトに直接doSomething()
を呼び出します。つまり、返されるタイプがA
かB
かどうかを知る必要はありません。あなたが気にするのは、それがdoSomething
です。ブーストを使用するオプションの場合はそれが多型の美しさ、すなわちこれ以上醜いis
、getType
、instanceOf
(ジャワ)、など
誤解を招くような、それは本当に、答えはC++の質問のためのJavaの答えではありませんOPには当てはまらない可能性のある選択肢への提案が含まれています。タグを見てください。 –
この例はJavaで、質問はC++です。それでも、C++で基本的に同じことをすることができます。 C++で行うことができないことは、C++がすべてのクラスを自動的に共通のルート型から継承するよう強制しないので、 'Object'を返すときに後退します。 – bames53
@Jacoboあなたは深刻ですか?誰が言語を気にしているのかは、C++、C#、Java、PHPの場合は同じ原理ではありません...... – scibuff
で、Boost.Variantを使用することを検討してください。
変異体はステロイドでunion
と考えることができます。ほとんどのC++型で動作し、コンパイル時と実行時の多態性の両方を可能にしますが、型に共通の基本クラスは必要ありません。 主な欠点は、深刻な量のテンプレートメタプログラミングが必要なため、コンパイラに多少の負担がかかることです。
ここでは簡単な例は、アイデアを得るためにです:
typedef boost::variant<float, std::string> MyVariant;
MyVariant GetInt() { return MyVariant(42); }
MyVariant GetString() { return MyVariant("foo"); }
MyVariant v;
//run-time polymorphism:
int number = boost::get<int>(v); // this line may throw (basically a dynamic_cast)
//compile time polymorphism:
boost::apply_visitor(Visitor(), v);
// where Visitor is a functor overloading operator() for *all* types in the variant
より軽量の代替はBoost.Anyあり、比較のためにthis pageを参照してください。
Boost.Anyは、タイプ消去が必要なので、はるかに重い代替品です。しかし、Boost.Variantを推薦するのに+1。 – ildjarn
軽量はおそらく言葉の悪い選択だった。私が言っていることは、AnyはVariantよりも学びやすく使いやすいということです。混乱させて申し訳ありません。 – ComicSansMS
は多型を使用する。 (もちろん、これはユーザ定義の型に対してのみ動作します)代わりに 'Object'型を返すようにメソッドを宣言できますが、これはあまりエレガントではありません – scibuff
いくつかの限られたケースでは、 「組合」(何かがそれを弁別することを提供する)。一般に、多型がより良い。 –
@scibuff:これを回答として投稿する必要があります。 –