通过匿名 类

Passing Anonymous Classes

这是 Java 的问题。我有一个名为 IMyObjectPredicate 的接口,它实现了一个应用于输入的测试方法:

public interface IMyObjectPredicate {
    boolean test(MyObject x);
}

我想要的是能够在对象之间传递 IMyObjectPredicate 的实例,并让 test 函数将其对变量的引用更新为正在传递的新对象的变量到。例如,考虑使用此谓词的 class:

public class Tester {
    MyObject o;
    IMyObjectPredicate myTestFunction;
    int myThreshold;

    public Tester(/*stuff*/) {
        /*Code here which initialises the Tester instance and 'myThreshold'*/
        myTestFunction = new IMyObjectPredicate() {
            @Override
            public boolean test(MyObject o) {
                return (o.value() > myThreshold);
            }
        };
    }

    public boolean isGood() {
        return myTestFunction.test(o);
    }
}

我希望能够执行 Tester 对象的深度克隆,原因我不会在这里详述。但想法是 Tester 的克隆实例应该根据其 ownmyThreshold 测试谓词,而不是引用第一个的 myThreshold实例。但是,如果我将 myTestFunction 传递给 Tester 的新实例,我猜它仍将引用第一个实例的 myThreshold 值,而不是动态评估 myThreshold 基于封闭 class.

的引用

如何完成 IMyObjectPredicate 对象的传递,该对象的测试函数使用对传递给 的 新对象字段的引用?

编辑: 一个复杂的因素是,一般来说,不可能仅从 Tester 对象中的字段重建 myTestFunctionmyTestFunction 可能会以与 Tester 的其他字段无关的方式被程序的其他部分覆盖。如果需要我可以牺牲这个功能,但为了优雅我宁愿不这样做。

Java 没有 API 来替换匿名 class 的封闭上下文。

我从您的简化示例中看到的最简单的解决方案是在测试函数的签名中添加阈值。据我了解,阈值无论如何都会存在。

public interface IMyObjectPredicate {
    boolean test(MyObject x, int threshold);
}

另一种方法是使用一些工厂方法来为提供的阈值创建谓词,例如

class PredicateFactory {
    IMyObjectPredicate thresholdPredicate(int threshold) {
        return new IMyObjectPredicate {
              //...
        }
    }
}

然后你可以将这个工厂传递给对象,对象将使用它自己的阈值来构造谓词的新实例

factory.thresholdPredicate(myThreshold);

如果 ImObjectPredicate 是一个只存储对谓词而不是接口的引用的 class,那就容易多了。如果您能够进行更改,则每个谓词都可以存储自己的阈值,从而解决问题。

public IMyObjectPredicate {
    private int threshold;
    private Predicate<MyObject> pred;

    public int getThreshold() {
        return threshold;
    }

    public Predicate<MyObject> getPredicate() {
        return pred;
    }

    public IMObjectPredicate(int threshold, Predicate<MyObject> pred) {
        this.threshold = threshold;
        this.pred = pred;
    }

    public boolean test(MyObject o) {
        return pred.test(o);
    }
}

public class Tester {
    MyObject o;
    IMyObjectPredicate myTestFunction;
    IMyObjectPredicate myTestFunctionCopyWithDiffThreshold;
    int myThreshold;

    public Tester(/*stuff*/) {
        /*Code here which initialises the Tester instance and 'myThreshold'*/
        myTestFunction =
            new IMyObjectPredicate(myThreshold, o -> o.value() > getThreshold());
        myTestFunctionCopyWithDiffThreshold =
            new ImObjectPredicate(5, myTestFunction.getPredicate());
    }

    public boolean isGood() {
        return myTestFunction.test(o);
    }
}

这是最明智的解决方案,因为 ImObjectPredicate 应该 存储自己的阈值,如果该值唯一地引用 ImObjectPredicate