OVERRIDE_BY_INLINE in Kotlin - oop

When implementing an interface in Kotlin with an inline function:
interface Foo {
fun qux(fn: () -> Unit)
}
open class Bar : Foo {
final override inline fun qux(fn: () -> Unit){TODO()}
}
the IDE (and possibly the compiler) complains with this message:
Override by an inline function
To suppress this message, I have to use the #Suppress("OVERRIDE_BY_INLINE") annotation. What is wrong?
What I am already aware:
For a normal inline function, kotlinc will inline all usages of the inline function, but it will still compile the non-inline version of the function so that it can be called from Java (and possibly for backward compatibility or whatever reason).
It is impossible to inline a virtual method. Inline simply means "copy all the code into the caller", but for invoking an abstract/interface method, the implementation is determined at runtime based on the actual class of the object involved, so it is not possible to know which implementation to copy into the function.
However, this isn't the case when invoking a final function. In the example above, when I invoke bar.qux(), the compiler can ensure that only this particular implementation will be used, and can safely inlined. It is irrelevant with whether it overrides the Foo.qux method -- calling foo.qux will use the non-inline version mentioned in point 1, and calling bar.qux can inline safely.
Is this warning there only to make sure developers are aware of this? Or are there side effects?

I know this is pretty late, but here's why. You got this right:
It is impossible to inline a virtual method.
But you should consider that, while Bar.foo is not virtual in the sense that it could be overridden (it can't be), it is virtual in the sense that a decision can be made to run it at runtime. Consider the following example which builds on your own:
interface Foo {
fun qux(fn: () -> Unit)
}
open class Bar : Foo {
final override inline fun qux(fn: () -> Unit){TODO()}
}
class Baz : Foo {
override fun qux(fn: () -> Unit) = TODO()
}
fun main() {
var foo: Foo = Bar()
foo.qux { } // calls Bar.qux
foo = Baz()
foo.qux { } // calls Foo.qux
}
Here, Bar.qux is invoked initially, but Baz.qux is invoked the second time. So, not every call can be inlined. So why is this a warning and not a compiler error, like when we declare an open fun with the inline modifier? Consider the following:
val bar: Bar = Bar()
bar.qux { }
In this case, the compiler can safely inline all calls to qux on the variable bar because it's declared as a Bar. Even if the class is open as in your example, since the method itself is final, any derived type will always use exactly that qux. So this statement,
In the example above, when I invoke bar.qux(), the compiler can ensure that only this particular implementation will be used, and can safely inlined.
is true only when the compiler statically knows the type of bar to be an actual Bar. It's an error when it's open because none of them can be inlined which definitely isn't the desired behavior, it's a warning when it's an override because only some of them can be inlined, which might not be the desired behavior.
This example is available at play.kotlinlang.org

Related

How to avoid NPEs from default parameters in mocked classes?

Here's a simplified version of what I want to test with Mockito:
class UnderTest {
fun doSomething() {
foo.doAnything()
}
}
class Foo {
fun doAnything(bar: Bar = Bar())
}
class TestUnderTest {
#Mock
var underTest: UnderTest
#Test
fun testDoSomething() {
underTest.doSomething() // Causes NPE
}
}
UnderTest is being tested. Its dependencies, like foo, are mocked. However, when my tests call UnderTest.doSomething(), it crashes. doSomething() calls Foo.doAnything(), letting it fill in the null parameter with the default - and the code that runs in that default parameter initialization is outside of the control of my test, as it's inside the static, synthetic method created for the byte code.
Is there a magical Mockito solution to get around this very situation? If so, I would love to hear it. Otherwise, I believe the options I have are:
To use PowerMock or Mockk to be able to mock things Mockito can't
To change Foo to have two doAnything() methods; one would have zero parameters, would call Bar() and pass it to the other.
To change Foo.doAnything() to accept a nullable parameter, then to have the body of the function call Bar() and use it.

Kotlin - Functional (SAM) interfaces VS Function types

With Kotlin 1.4 we now have Functional Interfaces
fun interface Todo {
fun run()
}
fun runBlock(todo: Todo){
if(condition)
todo.run()
}
fun runBlock{
println("Hello world")
}
Before i was always using (T) -> T
inline fun runBlock(block: ()-> Unit){
if(condition)
block()
}
fun runBlock{
println("Hello world")
}
So basically I can make the same task with both methods , there is any performance advantage by using Functional SAM() Interfaces over Function Type?.
It's a performance dis-advantage because the lambda is no longer inlined (unless the JIT decides to, but it won't be instant). Even if you mark runBlock as inline, the compiler will warn you that the argument won't be inlined.
There are only two reasons to use fun interfaces instead of function types:
Backwards compatibility when porting code using Java functional interfaces.
Not exposing Kotlin function types in API intended for use from Java.
To expand on point 1: before Kotlin 1.4 it was advised to keep functional interfaces as Java code, even if all your other code was Kotlin. This way you could use lambdas for parameters of those types both in Java and Kotlin code. But if you declared the interface in Kotlin, you could only use lambdas for them in Java.
https://kotlinlang.org/docs/reference/whatsnew14.html#sam-conversions-for-kotlin-interfaces
the compiler automatically converts the lambda to an instance of the class that implements the abstract member function.
So, no performance advantage, it’s the same thing as before. The compiler now does what you had to do before.
As other answers and comments have pointed out, in your case, using inlined lambda is faster, since there is no function call overhead when invoking it.
However, there is one specific use case where using SAM interface is faster, that is when you 1. do not inline the lambda and 2. the arguments/return value of the lambda is a primitive (or any other type that may cause boxing when used with generics).
For example, using SAM interface like so:
fun interface Foo() {
fun run(i: Int): Int
}
fun foo(fn: Foo) {
fn.run(42)
}
foo { it * 2 }
Will not cause any boxing when invoked, while:
fun foo(fn: (Int) -> Int) {
fn(42)
}
foo { it * 2 }
Will box the integer argument since (Int) -> Int is essentially Function1<Integer, Integer> in Java, which uses generic.

why there is 'by' for the extended class and reified in function define

coming across a sample with a class and a function and trying to understand the koltin syntax there,
what does this IMeta by dataItem do? looked at https://kotlinlang.org/docs/reference/classes.html#classes and dont see how to use by in the derived class
why the reified is required in the inline fun <reified T> getDataItem()? If someone could give a sample to explain the reified?
class DerivedStreamItem(private val dataItem: IMeta, private val dataType: String?) :
IMeta by dataItem {
override fun getType(): String = dataType ?: dataItem.getType()
fun getData(): DerivedData? = getDataItem()
private inline fun <reified T> getDataItem(): T? = if (dataItem is T) dataItem else null
}
for the reference, copied the related defines here:
interface IMeta {
fun getType() : String
fun getUUIDId() : String
fun getDataId(): String?
}
class DerivedData : IMeta {
override fun getType(): String {
return "" // stub
}
override fun getUUIDId(): String {
return "" // stub
}
override fun getDataId(): String? {
return "" // stub
}
}
why the reified is required in the inline fun <reified T> getDataItem()? If someone could give a sample to explain the reified?
There is some good documentation on reified type parameters, but I'll try to boil it down a bit.
The reified keyword in Kotlin is used to get around the fact that the JVM uses type erasure for generic. That means at runtime whenever you refer to a generic type, the JVM has no idea what the actual type is. It is a compile-time thing only. So that T in your example... the JVM has no idea what it means (without reification, which I'll explain).
You'll notice in your example that you are also using the inline keyword. That tells Kotlin that rather than call a function when you reference it, to just insert the body of the function inline. This can be more efficient in certain situations. So, if Kotlin is already going to be copying the body of our function at compile time, why not just copy the class that T represents as well? This is where reified is used. This tells Kotlin to refer to the actual concrete type of T, and only works with inline functions.
If you were to remove the reified keyword from your example, you would get an error: "Cannot check for instance of erased type: T". By reifying this, Kotlin knows what actual type T is, letting us do this comparison (and the resulting smart cast) safely.
(Since you are asking two questions, I'm going to answer them separately)
The by keyword in Kolin is used for delegation. There are two kinds of delegation:
1) Implementation by Delegation (sometimes called Class Delegation)
This allows you to implement an interface and delegate calls to that interface to a concrete object. This is helpful if you want to extend an interface but not implement every single part of it. For example, we can extend List by delegating to it, and allowing our caller to give us an implementation of List
class ExtendedList(someList: List) : List by someList {
// Override anything from List that you need
// All other calls that would resolve to the List interface are
// delegated to someList
}
2) Property Delegation
This allows you to do similar work, but with properties. My favorite example is lazy, which lets you lazily define a property. Nothing is created until you reference the property, and the result is cached for quicker access in the future.
From the Kotlin documentation:
val lazyValue: String by lazy {
println("computed!")
"Hello"
}

How to implement custom casting

I would like to implement custom conversion function of my class Foo to be able to pass it to the function that requres Bar object.
Equivalent C++ construction https://en.cppreference.com/w/cpp/language/cast_operator
class Foo {
operator Bar () {...}
}
Kotlin does not have implicit conversions, as an intentional design decision. You would need to make it explicit. You can do this either putting the burden on the caller, or on the receiver.
For example, if I had:
class One()
class Two()
object Utilities {
fun foo(one: One) {
...
}
}
If I want to pass an instance of Two to foo() I would either:
// add extension function for explicit conversion:
fun Two.toOne(): One { ... convert my instance to other type }
// now caller must convert:
Utilities.foo(myTwo.toOne())
The burden above is on the caller to convert, given this new extension function to do the conversion. This is typical of how Kotlin handles everything in the standard library.
But maybe you want to make it feel more implicit, so you could also add:
// add an extension to the callee, for implicit conversion:
fun Utilities.foo(two: Two) { foo(two.toOne()) }
// now caller doesn't have to convert:
Utilities.foo(myTwo)
Now the caller never sees the conversion, although they have to import your extension function and their IDE hopefully will auto-suggest this for them. So it feels implicit but they had to choose to use that extension, which is easy to do.
Notice that none of the extension functions above needed any modifications to the actual classes. These extensions can be imported individually or in the whole package import. They can be done independently from classes you do or do not control. They can be done from anywhere at any time.
Final code, in its entirety:
// original classes
class One()
class Two()
object Utilities {
fun foo(one: One) {
...
}
}
// extensions
fun Two.toOne(): One {
// ... convert my instance to other type
}
fun Utilities.foo(two: Two) { foo(two.toOne()) }
And now you can use either model as your code style desires.

What is the difference between crossinline and noinline in Kotlin?

This code compiles with a warning (insignificant performance impact):
inline fun test(noinline f: () -> Unit) {
thread(block = f)
}
This code does not compile (illegal usage of inline-parameter):
inline fun test(crossinline f: () -> Unit) {
thread(block = f)
}
This code compiles with a warning (insignificant performance impact):
inline fun test(noinline f: () -> Unit) {
thread { f() }
}
This code compiles with no warning or error:
inline fun test(crossinline f: () -> Unit) {
thread { f() }
}
Here are my questions:
How come (2) does not compile but (4) does?
What exactly is the difference between noinline and crossinline?
If (3) does not generates a no performance improvements, why would (4) do?
From the inline functions reference:
Note that some inline functions may call the lambdas passed to them as parameters not directly from the function body, but from another execution context, such as a local object or a nested function. In such cases, non-local control flow is also not allowed in the lambdas. To indicate that, the lambda parameter needs to be marked with the crossinline modifier
Hence, example 2. doesn't compile, since crossinline enforces only local control flow, and the expression block = f violates that. Example 1 compiles, since noinline doesn't require such behavior (obviously, since it's an ordinary function parameter).
Examples 1 and 3 do not generate any performance improvements, since the only lambda parameter is marked noinline, rendering the inline modifier of the function useless and redundant - the compiler would like to inline something, but everything that could be has been marked not to be inlined.
Consider two functions, A and B
A
inline fun test(noinline f: () -> Unit) {
thread { f() }
}
B
fun test(f: () -> Unit) {
thread { f() }
}
Function A behaves like function B in the sense that the parameter f will not be inlined (the B function doesn't inline the body of test whereas in the A function, the body: thread { f() } still gets inlined).
Now, this is not true in the example 4, since the crossinline f: () -> Unit parameter can be inlined, it just cannot violate the aforementioned non-local control flow rule (like assigning new value to a global variable). And if it can be inlined, the compiler assumes performance improvements and does not warn like in the example 3.
Let me try to explain this by example: I'll go through each of your examples and describe what it orders the compiler to do. First, here's some code that uses your function:
fun main(args: Array<String>) {
test {
println("start")
println("stop")
}
}
Now let's go through your variants. I'll call the functions from your examples test1..test4 and I'll show in pseudocode what the above main function would compile into.
1. noinline, block = f
This code compiles with a warning (insignificant performance impact)
inline fun test1(noinline f: () -> Unit) {
thread(block = f)
}
fun compiledMain1() {
val myBlock = {
println("start")
println("stop")
}
thread(block = myBlock)
}
First, note there's no evidence of inline fun test1 even existing. Inline functions aren't really "called": it's as if the code of test1 was written inside main(). On the other hand, the noinline lambda parameter behaves same as without inlining: you create a lambda object and pass it to the thread function.
2. crossinline, block = f
This code does not compile (illegal usage of inline-parameter)
inline fun test2(crossinline f: () -> Unit) {
thread(block = f)
}
fun compiledMain2() {
thread(block =
println("start")
println("stop")
)
}
I hope I managed to conjure what happens here: you requested to copy-paste the code of the block into a place that expects a value. It's just syntactic garbage. Reason: with or without crossinline you request that the block be copy-pasted into the place where it's used. This modifier just restricts what you can write inside the block (no returns etc.)
3. noinline, { f() }
This code compiles with a warning (insignificant performance impact)
inline fun test3(noinline f: () -> Unit) {
thread { f() }
}
fun compiledMain3() {
val myBlock = {
println("start")
println("stop")
}
thread { myBlock() }
}
We're back to noinline here so things are straightforward again. You create a regular lambda object myBlock, then you create another regular lambda object that delegates to it: { myBlock() }, then you pass this to thread().
4. crossinline, { f() }
This code compiles with no warning or error
inline fun test4(crossinline f: () -> Unit) {
thread { f() }
}
fun compiledMain4() {
thread {
println("start")
println("stop")
}
}
Finally this example demonstrates what crossinline is for. The code of test4 is inlined into main, the code of the block is inlined into the place where it's used. But, since it's used inside the definition of a regular lambda object, it can't contain non-local control flow.
About the Performance Impact
The Kotlin team wants you to use the inlining feature sensibly. With inlining the size of the compiled code can explode dramatically and even hit the JVM limits of up to 64K bytecode instructions per method. The main use case is higher-order functions that avoid the cost of creating an actual lambda object, only to discard it right after a single function call which happens right away.
Whenever you declare an inline fun without any inline lambdas, inlining itself has lost its purpose. The compiler warns you about it.
Q1: How come (2) does not compile but (4) does?
From their doc:
Inlinable lambdas can only be called inside the inline functions or passed as inlinable arguments...
Answer:
The method thread(...) is not an inline method so you won't be able to pass f as an argument.
Q2: What exactly is the difference between noinline and crossinline?
Answer:
noinline will prevent the inlining of lambdas. This becomes useful when you have multiple lambda arguments and you want only some of the lambdas passed to an inline function to be inlined.
crossinline is used to mark lambdas that mustn't allow non-local returns, especially when such lambda is passed to another execution context. In other words, you won't be able to do a use a return in such lambdas. Using your example:
inline fun test(crossinline f: () -> Unit) {
thread { f() }
}
//another method in the class
fun foo() {
test{
//Error! return is not allowed here.
return
}
}
Q3: If (3) does not generates a no performance improvements, why would (4) do?
Answer:
That is because the only lambda you have in (3) has been marked with noinline which means you'll have the overhead cost of creating the Function object to house the body of your lamda. For (4) the lambda is still inlined (performance improvement) only that it won't allow non-local returns.
To the first and second question
How come (2) does not compile but (4) does?.. difference between noinline and crossinline
2. inline fun test(crossinline f: () -> Unit) {
thread(block = f)
}
4. inline fun test(crossinline f: () -> Unit) {
thread { f() }
}
Both cases have inline modifier instructing to inline both the function test and its argument lambda f. From kotlin reference:
The inline modifier affects both the function itself and the lambdas
passed to it: all of those will be inlined into the call site.
So the compiler is instructed to place the code (inline) instead of constructing and invoking a function object for f. crossinline modifier is only for inlined things: it just says that the passed lambda (in f parameter) should not have non-local returns (which "normal" inlined lambdas may have). crossinline can be thought of as something like this (instruction to the compiler ): “ do inline but there is a restriction that it is crossing the invoker context and so make sure the lambda does not have non-local returns.
On a side note, thread seems like a conceptually illustrative example for crossinline because obviously returning from some code (passed in f) later on a different thread cannot possibly affect the return from test, which continues to execute on the caller thread independently from what it spawned (f goes on to execute independently)..
In case #4, there is a lambda (curly braces) invoking f(). In case #2, f is passed directly as an argument to thread
So in #4, call f() can be inlined and the compiler can guarantee there is no non-local return. To elaborate, the compiler would replace f() with its definition and that code is then “wrapped” inside the enclosing lambda, in other words, { //code for f() } is sort of another (wrapper) lambda and it itself is further passed as a function object reference (to thread).
In case #2, the compiler error simply says it cannot inline f because it is being passed as a reference into an “unknown” (non-inlined) place. crossinline becomes out of place and irrelevant in this case because it could be applied only if f were inlined.
To sum up, case 2 and 4 are not the same by comparing to the example from the kotlin reference (see "Higher-Order Functions and Lambdas"): below invocations are equivalent, where curly braces (lambda expression) "replace" the wrapper function toBeSynchronized
//want to pass `sharedResource.operation()` to lock body
fun <T> lock(lock: Lock, body: () -> T): T {...}
//pass a function
fun toBeSynchronized() = sharedResource.operation()
val result = lock(lock, ::toBeSynchronized)
//or pass a lambda expression
val result = lock(lock, { sharedResource.operation() })
Case #2 and #4 in the question are not equivalent because there is no "wrapper" invoking f in #2