Reputation: 904
This is a question for Java. I have an interface called IMyObjectPredicate
which implements a single test method to apply to an input:
public interface IMyObjectPredicate {
boolean test(MyObject x);
}
What I would like is to be able to pass an instance of IMyObjectPredicate
around between objects and have the test
function update its references to variables to those of the new object it is being passed to. For instance, consider a class which makes use of this predicate:
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);
}
}
I would like to be able to perform a deep clone of the Tester object for reasons I won't go into here. But the idea is that the cloned instance of Tester
should test the predicate against its own value of myThreshold
, not reference the myThreshold
of the first instance. But if I pass myTestFunction
to a new instance of Tester
, I guess it will still be referencing the myThreshold
value of the first instance, instead of dynamically evaluating myThreshold
based on the reference of the enclosing class.
How can I accomplish the passing of a IMyObjectPredicate
object whose test function uses references to the fields of the new object it is passed to?
Edit:
A complicating factor is that, in general, it will not be possible to reconstruct myTestFunction
solely from the fields within a Tester
object. myTestFunction
may be overwritten by other parts of the program in a way that does not correlate with the other fields of Tester
. I can sacrifice this functionality if need be, but I would rather not for the sake of elegance.
Upvotes: 0
Views: 247
Reputation: 7032
It is a lot easier if ImObjectPredicate
is an class that simply stores a reference to a predicate instead of an interface. If you're able to make that change, each predicate can store its own threshold, which solves the issue.
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);
}
}
This is the most sensible solution, as ImObjectPredicate
should store its own threshold if that value uniquely refers to that ImObjectPredicate
.
Upvotes: 0
Reputation: 4342
Java does not have an API to replace enclosed context of anonymous class.
The simplest solution I can see from your simplified example is to add threshold to the signature of test function. As I understand the threshold is going to be there anyway.
public interface IMyObjectPredicate {
boolean test(MyObject x, int threshold);
}
Another approach would use some factory method that will create a predicate for provided threshold like
class PredicateFactory {
IMyObjectPredicate thresholdPredicate(int threshold) {
return new IMyObjectPredicate {
//...
}
}
}
then you can pas this factory to object that will use it's own threshold to construct new instance of predicate
factory.thresholdPredicate(myThreshold);
Upvotes: 2