gpt4 book ai didi

java - 多个参数的多重分派(dispatch)

转载 作者:搜寻专家 更新时间:2023-11-01 02:59:23 25 4
gpt4 key购买 nike

有没有一种优雅的方法可以在 OO 语言中使用(单个)动态分派(dispatch)为具有 2 个(或更多)参数的方法获得多个分派(dispatch)?

可能的问题示例:

这是一个受 Java 启发的示例。(问题与语言无关!)

// Visitable elements
abstract class Operand {
}
class Integer extends Operand {
int value;
public int getValue() {
return value;
}
}
class Matrix extends Operand {
int[][] value;
public int[][] getValue() {
return value;
}
}

// Visitors
abstract class Operator {
// Binary operator
public Operand eval(Operand a, Operand b) {
return null; // unknown operation
}
}
class Addition extends Operator {
public Operand eval(Integer a, Integer b) {
return new Integer(a.getValue() + b.getValue());
}
}
class Multiplication extends Operator {
public Operand eval(Integer a, Integer b) {
return new Integer(a.getValue() * b.getValue());
}
// you can multiply an integer with a matrix
public Operand eval(Integer a, Matrix b) {
return new Matrix();
}
}

我有很多运算符和操作数具体类型,但只通过它们的抽象类型引用它们:

Operand a = new Integer()
Operand b = new Matrix();
Operand result;
Operator mul = new Multiplication();
result = mul.eval(a, b); // Here I want Multiplication::eval(Integer, Matrix) to be called

最佳答案

我决定对此进行补充,因为以上两个答案有些不完整。我自己对这个问题很好奇,但找不到答案,所以不得不自己分析。一般而言,有两种方法可用于在 C++ 或 Java 等语言中实现多方法,这些方法同时支持单个动态调度和类似 typeof 或运行时类型识别的东西。

对于双分派(dispatch)情况,访问者模式是最常见的(对于 Arg1->foo(Arg2) ),我认为在大多数情况下比使用 RTTI 和开关或 if 语句更受欢迎。还可以将访问者方法推广到 n 情况,即 Arg1->foo(Arg2,Arg3..ArgN),通过链接一系列调用树状结构中的方法的单个分派(dispatch),这些分派(dispatch)在参数类型上区分到一些k 并拆分 k+1 个参数的方式数。例如,对于三重分派(dispatch)的简单情况,每种类型只有两个实例:

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 个调度函数。

可以通过 instanceOf 运算符实现与运行时类型识别类似的功能:

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 );
}
}
}
}
}

第二种解决方案可能可以使用反射进一步简化。

关于java - 多个参数的多重分派(dispatch),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40386379/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com