Bick
Bick

Reputation: 18551

java 8 - how abstracts the use of predicates by using methods

I am trying to create a class that abstracts the use of predicates from its end user.

My app uses Guava-Retrying extension which works great.

Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
     .retryIfResult(Predicates.<Boolean>isNull())
     ....
     .build();
retryer.call(callable);

I can call easily call it with predicates and it polls until predicate returns false.

Now, maybe I misunderstand predicates but I am trying to create a class that will abstract them.

I wish to call it as follows

MyPoller.poll(new PollCondition<MyClass>() {
        @Override public boolean condition() {
            return !isValid(result**.getPermissions(), permissionName);
        }
    });

So I wrote PollCondition class as follows.

public abstract class PollCondition<T> {
  public Predicate<T> getCondition() {
      return result -> condition();
  }
  public abstract boolean condition();
} 

but MyPoller.poll() call fail to compile - result is not declared.

Any idea?

Upvotes: 3

Views: 1007

Answers (1)

JB Nizet
JB Nizet

Reputation: 692231

It seems you don't understand predicates indeed. A predicate is a function that takes an input as argument, and returns a boolean value (usually based on the input, of course).

Let's examine your PollCondition class:

public abstract class PollCondition<T> {
  public Predicate<T> getCondition() {
      return result -> condition();
  }
  public abstract boolean condition();
} 

So it defines an abstract condition() method that doesn't take anything as argument, and returns a boolean. And it can be "transformed" into a Predicate using getCondition(). This method returns a predicate which takes an input as argument (result), ignores it completely, and always returns the boolean returned by condition().

You then create a PollCondition using

new PollCondition<MyClass>() {
    @Override public boolean condition() {
        return !isValid(result.getPermissions(), permissionName);
    }
}

That would be correct if, in the scope where you execute that code, there was a variable named result. But there is not. result is in fact an input to your condition. So the class should in fact defined like this:

public abstract class PollCondition<T> {
  public Predicate<T> getCondition() {
      return result -> condition(result);
  }
  public abstract boolean condition(T result);
} 

And you would then be able to instantiate one using

new PollCondition<MyClass>() {
    @Override
    public boolean condition(MyClass result) {
        return !isValid(result.getPermissions(), permissionName);
    }
}

But I really, really don't see what that brings over using a simple Predicate directly.

Define MyPoller.poll() like this:

public poll(Predicate<T> predicate);

and use it like this:

MyPoller.poll(result -> !isValid(result.getPermissions(), permissionName));

Upvotes: 3

Related Questions