does anyone here know the answer?
# announcements
c
does anyone here know the answer?
q
This should work:
Copy code
val implementor: IImpl = /* some code that returns IImpl */
val zeroArityRef = { implementor.method() }
val twoArityRef = { a, b -> implementor.method(a, b) }
You could write functions that take in an implementor and return the function references you need to apply the pattern more generally.
w
Hey @christophsturm I can’t explain the “why” behind it, but it seems this works:
Copy code
val m: IImpl.() -> Unit = IImpl::method
val m2: IImpl.(Int, String) -> Unit = IImpl::method
c
thanks!
v
I can explain it 🙂
🙏 1
c
I think i can explain it too. IImpl is the type of this
v
Your initial try does not work, because what should they be called on? A function reference is the reference to a function on a receiver that can be invoked as is. If you have
"foo"::toString
then it is the reference to the function
toString
on the instance
"foo"
. In the first half of your example, the
::method
is a reference to the function
method
called on the instance
this
. In the second half of your example you try to get a function reference to an abstract function on an interface, so which receiver should this be called on if invoked? See, that's the problem. What
wbertan
showed works, because with the
IImpl.
at the type you say "this will be called on some actual instance of
IImpl
so no receiver is necessary yet. What you had in your original example could be called
m()
, what wbertan showed needs to be called
myInstanceOfIImpl.m()
.
c
actually i want to pass the method reference to a function. any idea how to get that to work?
Copy code
interface IImpl {
    fun method()
    fun method(number: Int, name: String)
}
// this does not work
val m3: IImpl.()->Unit = IImpl::method
val m4: IImpl.(Int, String)->Unit = IImpl::method


function(m4 as KCallable<*>)

fun function(callref: KCallable<*>) {println(callref)}
this works, but i cannot inline the variable m4
if its not overloaded this just works:
Copy code
function(IImpl::nonOverloadedMethod)
@Vampire are you talking about bound references? I just want something that references a method on a class, not an instance. the type is just there to differentiate between the two versions of the method.
v
Yep, that's the difference.
() -> Unit
is a send-contained function not taking any arguments and returning nothing that you can call like you have it, so it needs a receiver already as part of the reference.
IImpl.() -> Unit
is the reference to a method that you can call on an instance of
IImpl
, so the receiver is not part of the reference.
c
but if that is the only way to differentiate between 2 functions with the same name, that means its not possible to pass a function reference like
IImpl::foo
to a function that takes a kcallable.
v
Depending on what you want to do it cannot work anyway. If you for example want to call
callref
, then it will not work with
m3
or
m4
unless you also give an instance of
IImpl
as argument so that it has a receiver.
c
I just wanted an unbound callref, its the api of a mocking library,and the reason its not a string is just for autocomplete and refactorings. anyway i changed the api now.
v
So yes, afaik you are right, it is not possible to use a function reference for an overloaded function directly in that case, only via the separate variable where you can specify the type. But I'm not a Kotlin expert, I might be wrong. 🙂
c
for not being a kotlin expert you do know a lot!
😄 1