2

I'm pretty new in Java and have a question: is there any clean way to wrap code below in one function, which would get any expression (pointed by arrow) as a parameter?

Foo A, B;
...

try {
    wait.until(new Function<WebDriver, Boolean>() {
        public Boolean apply(WebDriver driver) {
            return A.equals(B); // <=================== some expression 
        }
}
catch (Exception ex) {
  return false;
}
return true;
szym4n
  • 25
  • 1
  • 4

3 Answers3

1

You need either an interface, or an abstract class to do this. An interface (out of the two) is the better choice in this case.

If a class implements an interface, then it must have the functions listed in the interface. Therefore, when you accept an interface in your function, you know that the object has the function listed (and you can call it).

You will define an interface like so:

public interface Test {
    public boolean passedTest();
}

Then you will define classes that implement Test:

public EqualsTest implements Test {
    private Foo A, B;
    public EqualsTest(Foo A, Foo B){
        this.A = A;
        this.B = B;
    }
    @Overrides
    public boolean passedTest(){
        return A.equals(B);
    }
} 

Then your function will look like the following:

public waitUntil(Test test){
    try{
        wait.until(new Function<WebDriver, Boolean>() {
            public Boolean apply(WebDriver driver) {
                return test.passedTest()
            }
        }
    } catch( Exception ex){
        return false;
    }
    return true;
}
Nathan Merrill
  • 7,648
  • 5
  • 37
  • 56
0

If you are not using Java 8 you need to use a Callback interface as below, then you call the generic method passing in an anonymous call that implements the interface and provides your validation logic in the call method body. Also see this answer

How to pass a function as a parameter in Java?

  @Test
    public void test() {    
        final Object a = new Object();
        final Object b = new Object();

        boolean result = waitUntil(new Callable() {
            public boolean call() {
                return a.equals(b);
            }
        });

        assertTrue(result);
    }

    public boolean waitUntil(final Callable func) {
        try {
            wait.until(new Function<WebDriver, Boolean>() {
                public Boolean apply(WebDriver driver) {
                    return func.call();// <=================== some expression 
                }
            }); 
        } catch (Exception ex) {
            return false;
        }
        return true;
    }


    public interface Callable {
        public boolean call();
    }
Community
  • 1
  • 1
omerio
  • 1,186
  • 7
  • 16
0

Yes -- sort of. If you are limited to Java 7 or below, it won't be as clean, but you can extract the logic into its own class, using something like the Abstract Factory method (I have done things like this several times for Selenium):

public abstract class FunctionFactory<T> {

    public abstract boolean execute(T t1, T t2);

    public static final FunctionFactory<T> WAIT_UNTIL_EQUALS = new FunctionFactory<T>() {

        @Override
        public boolean execute(T t1, T t2) {

            try {
                wait.until(new Function<WebDriver, Boolean>() {
                    public Boolean apply(WebDriver driver) {
                        return t1.equals(t2);
                    }
                }
            } catch (Exception ex) {
                return false;
            }
            return true;
        }

    }
}

Then, implement your method like so:

public boolean waitUntil(FunctionFactory factory, t1, t2) {
    return factory.execute(t1, t2);
}

Then you can call it like so:

waitUntil(WAIT_UNTIL_EQUALS, t1, t2);
James Dunn
  • 8,064
  • 13
  • 53
  • 87