2016-07-26 3 views
0

Это вопрос для Java. У меня есть интерфейс, который называется IMyObjectPredicate, который реализует один метод испытаний для применения к входу:Прохождение анонимных классов

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

То, что я хотел бы, чтобы быть в состоянии передать экземпляр IMyObjectPredicate вокруг между объектами и имеет функцию test обновить свои ссылки к переменным к переменным нового объекта, к которому он передается. Например, рассмотрим класс, который делает использование этого предиката:

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

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

Я хотел бы быть в состоянии выполнить глубокий клон объекта Tester по причинам, я не буду вдаваться в здесь. Но идея состоит в том, что клонированный экземпляр Tester должен проверить предикат на его собственный значение myThreshold, а не ссылку myThreshold первого экземпляра. Но если я передам myTestFunction в новый экземпляр Tester, я думаю, он все равно будет ссылаться на значение myThreshold первого экземпляра вместо динамической оценки myThreshold на основе ссылки окружающего класса.

Как я могу выполнить прохождение объекта IMyObjectPredicate, чья тестовая функция использует ссылки на поля нового объекта , он передан в?

Edit: осложняющим фактором является то, что, в общем, это не будет возможно восстановить myTestFunction исключительно из полей в пределах Tester объекта. myTestFunction может быть перезаписан другими частями программы таким образом, который не коррелирует с другими полями Tester. Я могу пожертвовать этой функциональностью, если понадобится, но я бы предпочел не ради элегантности.

+1

Я бы не ожидал, что это станет возможным.Но если это в конструкторе, вы можете просто создать новый предикат. –

+0

@LouisWasserman В общем, 'myTestFunction' будет изменен в ходе программы. Я хочу иметь возможность копировать его по требованию по мере необходимости. – Myridium

+0

У вашего анонимного метода 'IMyObjectPredicate' есть метод no-arg' test() ', но интерфейс требует, чтобы он принял аргумент' MyObject' ...? –

ответ

2

У Java нет API для замены замкнутого контекста анонимного класса.

Простейшим решением, которое я вижу из вашего упрощенного примера, является добавление порога к сигнатуре тестовой функции. Как я понимаю, порог будет там все равно.

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

Другой подход будет использовать какой-то фабричный метод, который будет создавать предикат для предусмотренного порога, как

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

, то вы можете па этот завод, чтобы объект, который будет использовать собственный порог, чтобы построить новый экземпляр предиката

factory.thresholdPredicate(myThreshold); 
+0

Хотя это не полностью решает мою проблему, +1 для «Java не имеет API для замены замкнутого контекста анонимного класса». То, что я отнимаю от этого ответа, состоит в том, что невозможно передать копию 'IMyObjectPredicate' так, как я хочу, если я не реализую явный метод для восстановления предиката из полей нового объекта Tester. Это позор, поскольку поля 'Tester' вообще не будут определять, что такое предикат. Предикат может быть независимо модифицирован другими частями программы. – Myridium

0

это намного проще, если ImObjectPredicate является класс, который просто хранит ссылку на предикат вместо интерфейса. Если вы в состоянии сделать это изменение, каждый предикат может сохранить свой собственный порог, который решает проблему.

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

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

Это наиболее разумным решением, так как ImObjectPredicateдолжен магазине своего собственного порога, если это значение однозначно указывает, что этот ImObjectPredicate.

+0

Согласно обновлению к моему вопросу, «ImObjectPredicate должен хранить свой собственный порог, если это значение однозначно относится к этому ImObjectPredicate» - к сожалению, это не так. Поля «Тестер» ** не ** однозначно определяют 'IMyObjectPredicate'. Возможно, я немного упростил этот пример. – Myridium

Смежные вопросы