A very nice and very simple syntactic transformation is to convert:
object1 function object2
into
object1.function(object2)
This allows you to write functions as infix operators.
This only works for methods, of course, and extension functions because it has to be possible to call the function with a sensible this value. It also only works with functions with a single parameter.
For example, we can define an infix extension function’s sum:
infix fun Int.sum(a:Int):Int {
return this+a
}
Now we can write:
1 sum 2
and get the result 3.
It is obvious, from the fact that you can use a function call in an expression, that infix functions can be used in expressions in a natural manner.
For example:
1 sum 2 * 3
is seven as multiplication has a higher priority than a function call.
Function Types
In most cases all you really need to know is the signature of a function, i.e. what the types are of its parameters and perhaps its return type. The signature of a function is used to determine which function is called if there are a number of overloads.
Sometimes, however, we need to define a type that corresponds to a particular signature and return type. For this we need to create a specific function type.
For example:
(String)->Int
defines a function type that takes a String and returns an Int.
Similarly:
(Int,Int)->Int
defines a function type that takes two Ints and returns an Int. As already introduced in Chapter 7 we can define a type alias to avoid having to type out a function type definition each time it is needed.
For example:
typealias arith =(Int,Int)->Int
Defines the arith type to be a function that takes two Ints and returns an Int.
The only not quite obvious function type is:
()->Unit
which is the type of a function taking no parameters and returning no result.
Summary
Kotlin gives the impression that you can define functions outside of classes i.e. functions that are not methods, but in fact it converts these into methods of a default class.
You can set the name of the default class using:
@file:JvmName("class name")
Local functions can access the containing functions variables but not vice versa.
All parameters are passed by value and are read-only val types.
As object references are passed as read-only values, referencing the this object means you can change properties on an object from within a function.
You can also use default, named and vararg parameters.
The receiver or call context is represented by this in methods.
For nested classes this can be qualified by the name for the class for which the call context is required.
Extension functions can make use of this to make them look as if they are methods of an existing class, but they cannot access the internal workings of the class.
Methods and extension functions with a single parameter can be used as infix operators with the object to the left as the call context, and the object on the right as the single parameter.
You can define a function type as the signature and return type of the function.
Are you ready for Thanksgiving, when overeating remorse and a surfeit of being thankful causes the unsettling thought that there are only four weeks till the Xmas break? So here is a mix of weird [ ... ]