を。私は自分自身でこの問題について興味があったが、答えを見つけることができなかったので、自分の分析をしなければならなかった。一般に、C++やJavaのような言語で複数のメソッドを実装するには、単一の動的ディスパッチと型やランタイム型の識別の両方をサポートする2つの方法があります。
ダブルディスパッチの場合、ビジターパターンが最も一般的です(Arg1-> foo(Arg2))。ほとんどの場合、RTTIとスイッチまたはif文を使用するよりも優先されます。引数の型をいくつかに区別するツリー構造のメソッドを呼び出す一連の単一ディスパッチを連鎖させることで、Arg1-> foo(Arg2、Arg3..ArgN)というnの場合の訪問者のアプローチを一般化することもできますkとk + 1引数のウェイ数を分割します。たとえば、トリプル派遣し、各タイプの唯一の2つのインスタンスの単純なケースのために:
interface T1 {
public void f(T2 arg2, T3 arg3);
}
interface T2 {
public void gA(A a, T3 arg3)
public void gB(B b, T3 arg3)
}
interface T3 {
public void hAC(A a,C c);
public void hAD(A a,D d);
public void hBC(B b,C c);
public void hBD(B b,D d);
}
class A implements T1 {
public void f(T2 arg2, T3 arg3) {
arg2->gA(this,arg3);
}
}
class B implements T1 {
public void f(T2 arg2, T3 arg3) {
arg2->gB(this,arg3);
}
}
class C implements T2 {
public void gA(A a,T arg3) {
arg3->hAC(a, this);
}
public void gB(B b,T arg3) {
arg3->hBC(b, this);
}
}
class D implements T2 {
public void gA(A a,T arg3) {
arg3->hAD(a, this);
}
public void gB(B b,T arg3) {
arg3->hBD(b, this);
}
}
class E implements T3 {
public void hAC(A a,C c) {
System.out.println("ACE");
}
public void hAD(A a,D d) {
System.out.println("ADE");
}
public void hBC(B b,C c) {
System.out.println("BCE");
}
public void hBD(B b,D d) {
System.out.println("BDE");
}
}
class F implements T3 {
public void hAC(A a,C c) {
System.out.println("ACF");
}
public void hAD(A a,D d) {
System.out.println("ADF");
}
public void hBC(B b,C c) {
System.out.println("BCF");
}
public void hBD(B b,D d) {
System.out.println("BDF");
}
}
public class Test {
public static void main(String[] args) {
A a = new A();
C c = new C();
E e = new E();
a.f(c,e);
}
}
アプローチは、問題を一般化けれども、非常に明白です。最悪の場合、各エンドポイント関数について、n-1ディスパッチ関数を書かなければならない。第二の溶液は、おそらくさらに反射を使用して簡素化することができる
class Functions
{
static void f(A a,C c,E e) {
System.out.println("ACE");
}
static void f(A a,C c,F f) {
System.out.println("ACF");
}
static void f(A a,D d,E e) {
System.out.println("ADE");
}
static void f(A a,D d,F f) {
System.out.println("ADF");
}
static void f(B b,C c,E e) {
System.out.println("BCE");
}
static void f(B b,C c,F f) {
System.out.println("BCF");
}
static void f(B b,D d,E e) {
System.out.println("BDE");
}
static void F(B b,D d,F f) {
System.out.println("BDF");
}
static void dispatch(T1 t1, T2 t2, T3 t3) {
if(t1 instanceOf A)
{
if(t2 instance of C) {
if(t3 instance of E) {
Function.F((A)t1, (C)t2, (E)t3);
}
else if(t3 instanceOf F) {
Function.F((A)t1, (C)t2, (F)t3);
}
}
else if(t2 instance of D) {
if(t3 instance of E) {
Function.F((A)t1, (D)t2, (E)t3);
}
else if(t3 instanceOf F) {
Function.F((A)t1, (D)t2, (F)t3);
}
}
}
else if(t1 instanceOf B) {
if(t2 instance of C) {
if(t3 instance of E) {
Function.F((B)t1, (C)t2, (E)t3);
}
else if(t3 instanceOf F) {
Function.F((B)t1, (C)t2, (F)t3);
}
}
else if(t2 instance of D) {
if(t3 instance of E) {
Function.F((B)t1, (D)t2, (E)t3);
}
else if(t3 instanceOf F) {
Function.F((B)t1, (D)t2, (F)t3);
}
}
}
}
}
:
一つはinstanceof演算子を介して実行時型識別と同様のものを達成することができます。
例evemはコンパイルされますか? (数値をオペランドに変換)。問題の内容をもう少し明確にすることができますか? – n247s
私はコンストラクタを書きませんでしたので、コンパイルされません。これは単なる例です。 呼び出すオブジェクトが静的型の演算子と実行時型の乗算を持ち、その引数が静的型のオペランドと実行時型のIntegerとMatrixを持つ場合、Multiplication :: eval(Integer、Matrix)を呼び出すことができます。このためのパターンが存在し、evalメソッドに引数が1つしかない場合は、複数ディスパッチと呼ばれます。私は2つ(またはそれ以上)の議論について同じことを望む。 – biowep
'Operator mul;'を定義するとすぐに、 'Operator'で定義された契約に制限されます。したがって、 'Operator'クラス(またはその親の1つ)で' eval(Integer、Matrix) 'メソッドを定義しない限り、それを呼び出すことはできません。これを 'Operator'型と宣言するのではなく、' Multiplication'に変更することができます。 – nickb