oop在Java中将一个类型泛化为一个类型系统
我有一些代码,其中有一个对象,比如事件,它有一组属性,任何人都可以通过调用事件方法:双getAttributeValue(整数索引)。 到目前为止,该方法的特征码中的阿替布特值始终是双倍的。现在它可以是其他新类,我需要对代码进行泛化,所以任何应用于Double的运算符都应该在我的新类系统中工作。此外,这些类不仅应该像在旧代码中那样操作,一个到同一个类,还应该在一个到另一个之间与相同的操作符交互。 对于exmaple,旧代码的操作方式如下:
private Double calculateDelta(Event event) {
Double firstValue = (Double)event.getAttributeValue(StockEventTypesManager.firstStockMeasurementIndex);
Double secondValue = (Double)event.getAttributeValue(StockEventTypesManager.firstStockMeasurementIndex + 1);
return Math.abs(firstValue - secondValue);
}
新的代码应该是这样操作的:
private AttributeValue calculateDelta(Event event) {
AttributeValue firstValue = (AttributeValue )event.getAttributeValue(StockEventTypesManager.firstStockMeasurementIndex);
AttributeValue secondValue = (AttributeValue )event.getAttributeValue(StockEventTypesManager.firstStockMeasurementIndex + 1);
return Math.abs(AttrValueFunctional.minus(firstValue,secondValue));
}
或者类似的东西(这些只是建议,因为我不知道如何设计):
private AttributeValue calculateDelta(Event event) {
AttributeValue firstValue = (AttributeValue )event.getAttributeValue(StockEventTypesManager.firstStockMeasurementIndex);
AttributeValue secondValue = (AttributeValue )event.getAttributeValue(StockEventTypesManager.firstStockMeasurementIndex + 1);
return (firstValue.minus(secondValue)).abs();
}
其中,该代码可以对应于这些语句对中的每一个:
boolean isDoubleWrapper = firstValue isinstanceof DoubleWrapper; //true
boolean isDoubleList = secondValue isinstanceof DoublePairsList; //true
boolean isDoubleList = firstValue isinstanceof DoublePairsList; //true
boolean isDoubleWrapper = secondValue isinstanceof DoubleWrapper; //true
boolean isDoubleWrapper = firstValue isinstanceof DoubleWrapper; //true
boolean isDoubleWrapper = secondValue isinstanceof DoubleWrapper; //true
boolean isDoublePairsList = firstValue isinstanceof DoublePairsList; //true
boolean isDoublePairsList = secondValue isinstanceof DoublePairsList; //true
也可以是:
boolean isStrangeObject = firstValue isinstanceof StrangeObject; //true
boolean isDoubleList = secondValue isinstanceof DoublePairsList; //true
boolean isDoubleList = firstValue isinstanceof DoublePairsList; //true
boolean isStrangeObject = secondValue isinstanceof StrangeObject; //true
boolean isStrangeObject = firstValue isinstanceof StrangeObject; //true
boolean isStrangeObject = secondValue isinstanceof StrangeObject; //true
boolean isDoublePairsList = firstValue isinstanceof DoublePairsList; //true
boolean isDoublePairsList = secondValue isinstanceof DoublePairsList; //true
我伟大的设计目标是使未来的任何程序员都能轻松地添加一些新类,这些类可以“隐藏”在AttributeValue中,添加所需的操作功能(加法、减法、abs), 因此,新类应该具有良好的可伸缩性
我尝试了一些实现,其中一个通常有效(如下所示),但我不认为它遵循了最好的java设计模式,或者它具有良好的可扩展性,并且很容易添加我提到的新类
public class Main {
public interface Operand {}
public interface Combiner<T> {
T subtract(T a, T b);
}
public static abstract class MyFunctional {
public static<T extends Operand> T
compute(Operand a, Operand b, Subtracter combiner) {
return (T) combiner.subtract(a, b);
}
private static A subtractAA(A a, A b){
return new A(a.getFirst() - b.getFirst(), a.getSecond()-b.getSecond());
}
private static A subtractAB(A a, B b){
return new A(a.getFirst() - b.getFirst(), a.getSecond()-b.getSecond()-b.getThird());
}
static class
Subtracter implements Combiner<Operand> {
@Override
public Operand subtract(Operand x, Operand y) {
if(x instanceof A && y instanceof A){
return subtractAA((A)x,(A)y);
}
if(x instanceof A && y instanceof B){
return subtractAB((A)x,(B)y);
}
return null;
}
}
}
public static class A implements Operand{
private int a;
private int b;
public A(int a, int b){
this.a=a;
this.b=b;
}
public int getFirst(){
return a;
}
public int getSecond() {
return b;
}
@Override
public String toString() {
return "("+a+" "+b+")";
}
}
public static class B implements Operand {
private int a;
private int b;
private int c;
public B(int a, int b, int c){
this.a=a;
this.b=b;
this.c = c;
}
public int getFirst(){
return a;
}
public int getSecond() {
return b;
}
public int getThird() {
return b;
}
@Override
public String toString() {
return "("+a+" "+b+" "+c+")";
}
}
public static void main(String[] args) {
Operand e = new A(1, 2);
Operand f = new A(3,4);
Operand g = new B(3,4,5);
System.out.println("Hello World");
System.out.println((Object)MyFunctional.compute(e,f, new MyFunctional.Subtracter()));
Operand o = MyFunctional.compute(f,g, new MyFunctional.Subtracter());
System.out.println("Bye");
}
}
这是我尝试做的一个小例子。 任何人都可以尝试更改我的代码或为那些简单的A、B类建议自己的代码,这些类将很容易适应新的类(例如,如果想要添加一些简单的C类,包含4个字段,以及C和自身之间以及A和C、B和C之间的加法和减法运算),正如我在这里和《乞讨》中所描述的那样(实际上基本相同)
在回答几个问题后进行编辑: 新类型的真正领域: 所以在旧问题中,Double类型意味着一个确定性的值(它意味着这个值在现实世界中以1.0的概率已知)。 现在我需要用图片中的类型系统来替换它。 现在,关于操作和操作数功能: 同一分支中的每两个对象都应作为其自身的第一个祖先进行操作。 不同分支的两个对象应该像它们的第一个祖先一样执行相同的操作
因此,最终我想将代码重构为新的假设:
event.getAttributeValue(index);
可以返回所描述的可能层次结构中的任何类。 当然,现在我需要编写一个代码,只实现最左边的两个高位对象以及它们之间的所有操作,比如减法、加法等等。 我的目标是为这个问题设计正确的接口和类框架
由于上一次更新的答案,另一个澄清:
我想做的是某种包装和功能性策略设计模式,就像下面链接中的两个代码:
首先(不是模板化的示例,我需要根据最后更新的答案进行概括): first
second(类似于这样,但根据建议的解决方案使用Class、Class和BiFunction,以及BinaryOperator): second
# 1 楼答案
已经有一个类用于此:BinaryOperator
忘记像AttributeValue这样的包装类吧。只需让事件继续像以前一样保存简单的值,包括double,并将合并操作作为二进制运算符传递
由于类型擦除,强制转换为泛型类型(如
T
)是一种不安全的操作,因此您还需要传递类型:对该方法的调用如下所示:
更新:
您在注释中指出,操作数并不总是属于同一类型。在这种情况下,您将使用BiFunction而不是二进制运算符:
然而,事实证明你两者都能做到!对于期望两个值和结果都是相同类型的情况,可以使用上述方法,也可以使用第一个版本作为方便:
澄清:
BiFunction和BinaryOperator都是函数接口,也就是说,只有一个抽象方法的接口。(
static
和default
方法不是抽象方法。)这意味着可以使用lambda来表示它
(a, b) -> a - b)
与此相同:所以,lambda实际上是双函数或二进制运算符
它不一定非得是羔羊。它也可以作为方法参考:
当然,你可以让这种方法变得更复杂:
还可以定义复杂对象本身的操作: