Is there a way in Kotlin to inherit function types?
What I want is to have a member like so: private lateinit var onPickedFunc: (Any) -> Task<Void>? so I can dynamically store the functions I need to run after a user has made it's choice. For example:
private fun showImagePicker(func: (Uri) -> Task<Void>?) {
onPickedFunc = func
val intent =
Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI
)
startActivityForResult(intent, RC_PICK_IMAGE)
}
private fun showMenu(func: (Context) -> Task<Void>?, v: View) {
onPickedFunc = func
PopupMenu(context, v).apply {
// ProfileFragment implements OnMenuItemClickListener
setOnMenuItemClickListener(this@ProfileFragment)
inflate(R.menu.profile_settings_menu)
show()
}
}
I did find a group of classes called Function, but none of them allow inheritance in the input parameter (one of them allows inheritance in the output parameter: Function<out R>).
Is there any way to achieve that?
Thanks!
I think the issue here is one of variance.
funcis a function whose parameter is declared as aUri.But your
onPickedFuncproperty would be a function whose parameter can be anything. You should be able to call it with anInt, or aUri, or aString, or any other non-null value.So you can't assign
functo it, because that (probably) wouldn't be able to handle anIntor aStringor whatever.In technical terms, the types aren't compatible. Function parameters have
invariance (contravariance); to be a subtype, it must accept a supertype of each parameter. (This is the reverse of the function's return type, which hasoutvariance AKA covariance.) So the compiler would flag up a type mismatch.If you want to store your
(Uri) -> Task<Void>function in a property, it would have to be of type(Uri) -> Task<Void>or some supertype, which means the function would have to accept aUrior some subtype.(I don't know what type your
Uriis, but if it werefinal, likejava.net.URI, then the only subtype would beUriitself.)By the way, the
kotlin.jvm.functions.Function…interfaces are an implementation detail; the compiler uses them to implement function types on the JVM, but they're not something you should refer to in code (except in special cases such as reflection, I think).