I’m puzzled over SAM constructors, I have this Java class:
public class TestSam<T> {
public void observe(ZeroMethods zero, Observer<T> observer) {
}
public void observe(OneMethod one, Observer<T> observer) {
}
public void observe(TwoMethods two, Observer<T> observer) {
}
public interface Observer<T> {
void onChanged(@Nullable T t);
}
public interface ZeroMethods {
}
public interface OneMethod {
First getFirst();
}
public interface TwoMethods {
First getFirst();
Second getSecond();
}
public interface First {
}
public interface Second {
}
}
And this Kotlin code:
fun testSam(
test: TestSam<String>,
zero: TestSam.ZeroMethods,
one: TestSam.OneMethod,
two: TestSam.TwoMethods
) {
test.observe(zero) { println("onChanged $it") } // 1. compiles
test.observe(zero, TestSam.Observer { println("onChanged $it") }) // 2. Redundant SAM-constructor
test.observe(one) { println("onChanged $it") } // 3. doesn't compile
test.observe({ one.first }) { println("onChanged $it") } // 4. compiles
test.observe(one, TestSam.Observer { println("onChanged $it") }) // 5. compiles
test.observe(two) { println("onChanged $it") } // 6. compiles
test.observe(two, TestSam.Observer { println("onChanged $it") }) // 7. Redundant SAM-constructor
}
What's the deal here? Why can't Kotlin figure out 3. (and provides the special variant 4.), but handles all other cases?
The rationale for this code is LiveData<T>.observe(LifecycleOwner owner, Observer<T> observer)
method in Android, where LifecycleOwner
has one method getLifecycle()
.
I found a rule in compiler: if Java-method call requires types which is SAM-interfaces, then you can replace them with lambdas (or functions), but either all such parameters, or none of them.
So, you have method: public void observe(OneMethod one, Observer<T> observer)
.
Both parameters is SAM candidates. You can call:observer(object1, object2)
or:observer(function1, function2)
but not:observer(object1, function2)
and not:observer(function1, object2)
Same behaviour will be even in case of 3 or more parameters. The cause of this is technical difficulty in compiler design.
Sorry if I am not very clear, I'm not very good in English.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With