如何在java中定义不同对象之间的通用操作?

如何在java中定义不同对象之间的通用操作?,java,operator-overloading,code-reuse,Java,Operator Overloading,Code Reuse,我有许多不同类型的操作数,我想定义如何使用它们 这些操作数可以相互操作。这似乎是一个通用的 但我没有找到一个好的方法来实现它 首先,假设我有标量(即数字)、矩阵和集合 关于矩阵或标量,我想在这些上定义加号运算: scalar1.plus(scalar2)返回一个等于scalar1+scalar2的标量 matrix.plus(scalar1)或scalar.plus(matrix)都返回一个矩阵 其中“scalar1”每个元素都已添加到 矩阵 matrixSet.plus(matrix1)返回

我有许多不同类型的操作数,我想定义如何使用它们 这些操作数可以相互操作。这似乎是一个通用的 但我没有找到一个好的方法来实现它

首先,假设我有标量(即数字)、矩阵和集合 关于矩阵或标量,我想在这些上定义加号运算:

  • scalar1.plus(scalar2)返回一个等于scalar1+scalar2的标量

  • matrix.plus(scalar1)或scalar.plus(matrix)都返回一个矩阵 其中“scalar1”每个元素都已添加到 矩阵

  • matrixSet.plus(matrix1)返回一个集合,其中每个矩阵都已 添加到matrix1

等等。。。请注意,某些操作可能引发异常,例如 添加不同大小的矩阵或添加没有 相同数量的元素

我的目标如下:

1-尽可能多地重用代码(这很重要,因为我会有很多 更多操作和数据类型)

2-在编译时尽可能多地进行验证

3-便于将来添加新的数据类型或操作(例如 例如,我以后可能想添加一个向量数据类型)

我最初认为我应该定义一个操作数接口,我的 标量、矩阵和这些元素的集合将实现什么 将包括以下方法:

public Operand plus(Operand op);
这将允许be自下而上定义加号操作, 从最简单的元素(标量)开始:

然后对于矩阵:

public Operand plus(Operand operand) {
  if (Scalar.class.equals(operand.getClass())) {
    // return a matrix where we add scalar value to all matrix elements
  } else if (Matrix.class.equals(operand.getClass())) {
    // return a matrix where we perform a scalar addition between each element
  } else {
    // assume the other operand will define the addition for me
    // since add is commutative
    return operand.plus(this);
  }
}
其思想是每当我引入一个实现 操作数类型(比如向量),我只需要定义加号 新操作数与所有其他现有操作数之间的操作 操作数。也就是说,我不必重写 标量和矩阵类

此方法满足目标1和3,但不满足目标2:所有操作都返回 操作数对象,并迫使我进行大量的强制转换和类转换 在运行时检查,这似乎不是一个好的做法


有没有更好的方法来解决我的问题?

听起来你需要使用。基本上,您将定义一个通用接口,然后根据需要以多种方式调整接口以满足您的需要。

我不确定我是否完全理解您使用操作数接口的原因。似乎您的主要代码重用技术是在操作数已定义操作时调用该操作。但是界面的使用并不能帮助你做到这一点。我错过了什么?这样做不需要同样多的代码,但是允许一些好的事情,比如特定的返回类型和异常

标量:

public Scalar plus(Scalar operand) {
    return new Scalar(this.value + operand.getValue());
}

public Matrix plus(Matrix operand) {
    return operand.plus(this);
}
矩阵:

public Operand plus(Scaler operand) {
    return new Scalar(this.value + operand.getValue());
}

public Operand plus(Matrix operand){
  // return matrix plus matrix
}

经过反复思考之后,我发现我没有正确地解决问题,因为我为创建的每种类型的数据定义了操作。不管我怎么做,它都不管用

我最后做的是在整数上定义每个操作一个类。例如,加法、乘法、加法8比特等。此外,我有一个计算器类,在该类中,我定义了如何在两个块之间、一个块和一个整数之间、一组块和一个整数之间等基于整数之间的运算结果导出运算


这种方法解决了我上面列出的三个问题:代码中的零冗余、返回正确类型结果的方法,以及易于扩展到其他类型的方法。

使用java实现这一点的正确方法是在数据类中定义操作方法,并根据需要进行重载。如果您有一个矩阵类,那么该类需要知道如何向自身添加另一个矩阵,并向自身添加标量。我不知道分离操作数和运算符是否有特殊的原因,但除此之外,这是正确的方法。下面是一些代码来澄清这个概念:

class Matrix{
  Matrix add(Matrix m){
    //add matrix to self
    return this;
  }
  Matrix add(Scalar s){
    //add scalar to self
    return this;
  }
}

对于初学者,请使用
instanceof
操作符而不是
getClass()
谢谢。我读了一些关于适配器模式的书,但仍然无法理解在我现在的示例中如何使用它们。我会为每个数据类型组合创建一个适配器吗?这似乎太多了!请您给我一个具体的接口示例和一个或两个适配器,您将为我所提出的示例创建?@ Doudie07井,如果您正在执行的操作的数据结构是变化点,那么您可能应该考虑将数据结构变成表示构造函数的参数之一。在这一点上,您的程序将多态性地确定应该调用哪个适配器以成功地执行操作。这是我想到的第一种方法,也可能是我使用的方法。它的问题是代码大小增加了一倍,因为需要为每个操作数类型和每个类中的每个操作定义单独的方法。在上面的示例中,这个问题并不明显,但是假设有6种类型的操作数(矩阵、标量、向量和它们的集合对应物),现在必须为每种操作数编写6个加号方法:您失去了拥有一个操作数加号(操作数op)方法的能力,该方法包含您希望利用的所有加号操作。再说一次,不管怎样,我可能就是这么做的。
class Matrix{
  Matrix add(Matrix m){
    //add matrix to self
    return this;
  }
  Matrix add(Scalar s){
    //add scalar to self
    return this;
  }
}