Kotlin is a very feature rich language with and the subtleties of some of these features are worthy of some exploration to fully appreciate. In this ad-hoc series we’ll look at some of these, and in this article we’ll look at function references and some of the really nice tricks that we can achieve with them.
In Kotlin functions are first class and we can store the function in a variable and not just the result of a function. Moreover we can also pass around functions as arguments. Technically this is analogous to Java 8 method references, and this can be a very useful tool when it comes to delegating behaviour. Being able to delegate behaviour can make it much easier to de-couple our code, and can also make it much easier to write testable code. For Android we often hit testability issues when our code touches Android Framework and / or support library classes which may not be available in unit tests without using expensive testing frameworks such as Robolectric.
Let’s start by looking at a very simple function reference:
myFunc takes two arguments: The first is a boolean, and the second is a function reference.
myFunc itself contains the logic that is applied to the inputs, and
funcRef is only invoked in certain circumstances. However
myFunc is completely agnostic of what
funcRef actually does. It is also completely agnostic of how
someCondition is determined, it just applies the logic around it to determine whether
funcRef should be invoked. So, even in this very simple example, we can see how we can easily separate areas of responsibility.
We can take things a little further where we have a separate function defined which matches the signature of
This is behaviourally identical to the first example, but we can pass in a reference to an existing function.
If we take this a step further and make
doSomething members of separate classes we can see how we are each of these functions is executed within the context of its own class:
What’s important to note here is that the
doSomething references a private field of its class named
output. This field is only visible to members of
ClassOne so we can see how we are able to completely switch context using this mechanism. This can really help us in separating responsibilities by delegating behaviour to specific classes which are executed within the context of their enclosing class.
I mentioned earlier that this mechanism can help when it comes to removing dependencies on Android Framework classes. Let’s consider a simple example of looking up a colour resource value. Here are two distinct implementations for obtaining a colour value from the
Resources obtained from the
ClassOne has a dependency on
Context so will require either an Android Framework
Context instance either by being run as part of an Expresso test, or thorough a testing framework such as Robolectric, or with some mocking of both
ClassTwo has been implemented using a function reference to actually resolve the colour. We can pass in a reference to the
getColor method of ther
Resources instance to delegate the behaviour to the Android framework without
ClassTwo requiring any knowledge of the framework. To test this we can just pass in any implementation which matches the signature of that method:
The more observant may have noticed that
Resources#getColor is actually deprecated in API 23. Instead we might want to use
ContextCompat#getColor which provides backwards compatibility. However this is actually a static method, and static methods are difficult to mock, so can make our code less testable. However, a static method is still a function, and we can happily pass in a reference to a static method just as easily as a member function:
Of course we now have the dependency on
ClassThree but we could apply the techniques that we’ve already looked at to abstract this away.
So we haven’t done a really deep dive, nor have we even scratched the surface of how else we can use function references. But we’ve explored how we can use them to abstract out behaviour to keep our components discrete and with clear separation of responsibilities, while also covering some techniques of how we can avoid direct dependencies on Android Framework components. We’ve also made our code easier to write unit tests for. What’s not to like about all of this?
There is no stand-alone source for this article, as all of the gists are pretty self-contained.
© 2019, Mark Allison. All rights reserved.
Copyright © 2019 Styling Android. All Rights Reserved.
Information about how to reuse or republish this work may be available at http://blog.stylingandroid.com/license-information.