In the previous post, we looked at implicit parameters; parameters that will be automatically passed values annotated as
implicit. In this post, we’ll take a look at implicit functions and how they can be useful to convert things of one type to things of another.
Implicit functions will be called automatically if the compiler thinks it’s a good idea to do so. What that means is that if your code doesn’t compile but would, if a call was made to an implicit function, Scala will call that function to make it compile. They’re typically used to create implicit conversion functions; single argument functions to automatically convert from one type to another.
For example, the following function allows you to convert a Scala function into a instance of the Java 8
Consumer single argument method but still use Scala’s concise syntax.
You can avoid having to write clunky anonymous class instantiation when interfacing with Java and so mimic Java’s lambda syntax. So rather than having to use the longhand version like this.
You can write this, where we just pass a Scala function to Java’s
The argument to
forEach is actually a function of type
Element => Unit. Scala recognises that the
toConsumer method could convert this into a
Consumer[Element] and does so implicitly.
Which is basically short-hand for this.
If we have a button on we web page that we’d like to find using Web Driver, we’d normally write something like the following, using a “locator” to locate it by
It doesn’t take into account that the element might not be there when we call it (for example, when our UI uses ajax and adds the button asynchronously) and it’s also a bit verbose. We can use an implicit function to address both of these issues.
The fragment below uses the
WebDriverWait class to wait for a UI element to appear on the screen (using
findElement to check and retrying if necessary) and so smooths out the asynchronous issues.
It’s also an implicit function designed to convert a
By locator into a
WebElement. It means we can write something like the following where
button is no longer a
WebElement, but a
Without the implicit
waitForElement function, the code wouldn’t compile;
By doesn’t have a
click method on it. With the implicit function in scope however, the compiler works out that calling it (and passing in
create as the argument), would return something that does have the
click method and would compile.
Single Arguments Only Please
Now there’s one little bit I’ve brushed over here; namely how the
driver instance is made available. The example above assumes it’s available but it’d be nicer to pass it into the function along with
locator. However, there’s a restriction of passing only a single argument into an implicit function. The answer is to use a second argument (using Scala’s built in currying support). By combining implicit parameters the we saw in the previous post, we can maintain the elegant API.
So the full example would look like this; making
driver an implicit
val means we can avoid a call to
You can see from the examples above that implicit functions (and often combining them with implicit values) can make for succinct and more readable APIs. Next we’ll look at implicit classes.
If you’re interested in more Java bridge implicits like
toConsumer, check out this gist.