Unable to reference companion object methods - kotlin

I have the following code:
fun process(call: () -> Int) {
}
fun aa() = 5
class A {
companion object Factory {
fun bb() = 6
}
}
fun test() {
process(::aa) // OK
process(::A.bb) // Overload resolution ambiguity
}
When I try to call process(::A.bb) I get the following error:
Error:Overload resolution ambiguity:
public constructor A() defined in ru.netimen.hitch_hikingstats.A
public companion object Factory defined in ru.netimen.hitch_hikingstats.A
Is there any way to reference companion object methods?

In Kotlin 1.4+ you can use process(A::bb).
In 1.1.2+ you can use process(A.Factory::bb) or process((A)::bb).
Not so long after this question was asked Kotlin 1.1 was released with support for bound callable references:
https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md#11-m01-eap-1
https://blog.jetbrains.com/kotlin/2016/07/first-glimpse-of-kotlin-1-1-coroutines-type-aliases-and-more/
http://kotlinlang.org/docs/reference/whatsnew11.html#bound-callable-references
http://kotlinlang.org/docs/reference/reflection.html#bound-function-and-property-references-since-11
Kotlin 1.1.2 came with a fix for KT-15951, meaning that since then you can call process(A.Factory::bb).
There is also KT-13934 targeted for Kotlin 1.4, to support process(A::bb).

Syntactically it would be A.Factory:bb but it will not work. At first, bb is a A.Factory.() -> Int while () -> Int is required.
Secondly, callable references to object members are not supported at the moment as the Kotlin compiler says. Here's a parent task for all callable members tasks: https://youtrack.jetbrains.com/issue/KT-1183.

Related

Kotlin compile error using self generic type bound

Suppose I have the following code to simulate a state machine in Kotlin:
sealed interface State {
object A : State
object B: State
object C: State
object D: State
}
interface StateMachine<Self: StateMachine<Self, *>, T: State>
fun <S : StateMachine<S, State.A>> S.transitionX() = object : StateMachine<S, State.B> {}
fun <S: StateMachine<S, State.B>> S.transitionQ() = object : StateMachine<S, State.B> {}
object Start: StateMachine<Start, State.A>
fun main() {
val stateMachine = Start.transitionX().transitionQ()
}
However, this doesn't compile because
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public fun <S : StateMachine<TypeVariable(S), State.B>> TypeVariable(S).transitionQ(): StateMachine<TypeVariable(S), State.B> defined in root package in file Main.kt
which is probably because of the Self generic constraint.
Ideally, stateMachine should have a type StateMachine<StateMachine<Start, State.A>, State.B.
I was wondering if there's any way to fix the generic constraints so that this does compile? Note: I am aware that the Self generic parameter isn't actually needed for this state machine, but I'm just interested to see if this is actually possible.
I have tried a few different changes to the generic type bounds, but the closest I could get resulted in stateMachine just having a type of StateMachine<Start, State.B>, which isn't quite what I want. Other changes I've made have just caused the Kotlin Finite Bound Restriction error.
Any help is appreciated, thanks!
I don't know what you're trying to do with the self type, so it's hard to say whether these solutions will actually work for your use case.
You don't need to involve new generics in your function itself, only within its receiver and return type. So you can use * types to represent Self. This of course assumes that the Self type isn't needed outside its own private implementation, like if you had a fun copy(): Self. It's impossible to define an implementation of your interface using an anonymous object, since it has to have a class name to be able to describe its own self type. So you either need to define it with a named object outside the function, or by defining a class inside the function and returning an instance of it.
fun StateMachine<*, State.A>.transitionX(): StateMachine<*, State.B> {
class Impl: StateMachine<Impl, State.B>{
}
return Impl()
}
You could define explicit interfaces for all the possible children and use those. Since State is sealed, this is possible.
interface AStateMachine: StateMachine<AStateMachine, State.A>
interface BStateMachine: StateMachine<BStateMachine, State.B>
interface CStateMachine: StateMachine<CStateMachine, State.C>
interface DStateMachine: StateMachine<DStateMachine, State.D>
fun AStateMachine.transitionX() = object : BStateMachine {}
fun BStateMachine.transitionQ() = object : CStateMachine {}

How to understand Kotlin Functional Interface with companion object inside?

I would like to get some help to understand a Kotlin code snippet about functional interface used in Http4k org.http4k.core package
typealias HttpHandler = (Request) -> Response
fun interface Filter : (HttpHandler) -> HttpHandler {
companion object
}
I don’t understand the Filter interface, especially the companion object part. A typical functional interface is like this
fun interface IntPredicate {
fun accept(i: Int): Boolean
}
And you can create a lambda isEven
val isEven = IntPredicate { it % 2 == 0 }
According to this simple example, it looks like the interface Filter extends another interface (HttpHandler) -> HttpHandler? Then it defines a function signature companion object? Is this correct? What does the part companion object really mean?
Filter extends (HttpHandler) -> HttpHandler and the function type (HttpHandler) -> HttpHandler has a single abstract method (operator) - invoke - implicitly declared, like this:
operator fun invoke(HttpHandler): HttpHandler
So that is the function signature for the functional interface, not companion object.
companion object means what it has always meant - a companion object declaration. The companion object might seem empty, just from looking at the code you showed, and it makes one wonder what its purpose is. If you have removed the declaration, the functional interface would still have compiled, and can be used just like a functional interface representing the function type (HttpHandler) -> HttpHandler.
If you look further down the file, however, you'll see that there is (at least) one extension function declared on the companion object:
val Filter.Companion.NoOp: Filter get() = Filter { next -> { next(it) } }
This allows you to do val noOp = Filter.NoOp for example, so the companion object isn't that pointless.

syntax for generic-parameterized variable/constant

I'm trying to create a Map that contains generic-parameterized types. For example:
abstract class Foo {
companion object {
val fooInjectors = HashMap<Class<T: Foo>, Injector<T: Foo>>()
}
}
The idea is to have fooInjectors (which would be static in Java or in a companion object in Kotlin) contain a cache of sub-classes of Foo and their corresponding Injector.
Unfortunately, I can't get this to compile. I'd very much appreciate it if someone would help me figure out the syntax for this!
As far as I know, you are trying to do something that is impossible in Kotlin. The companion object is a singleton and it doesn't make sense to generify a singleton as there will not be any further objects created hence generic types are irrelevant. So you can't generify the property you declared because it's in the companion object.
However, one way you could make this working is using a backing function. This backing function should annotate with declaration-site variance.
This simply means we tell the compiler that we only return a type T from the method (and don't consume). That allows us to use subtypes and the supertype of the T if required. This is called covariance.
You can look at the docs to understand it further - https://kotlinlang.org/docs/reference/generics.html#declaration-site-variance
Here's what I meant.
interface Injector<T>
class InjectorImpl<T> : Injector<T>
abstract class Foo {
companion object {
val fooInjectors = createMap<Foo>()
private fun <T> createMap(): HashMap<Class<out T>, Injector<out T>> {
return HashMap()
}
}
}
class Bar: Foo()
object Runner {
#JvmStatic
fun main(args: Array<String>) {
Foo.fooInjectors[Bar::class.java] = InjectorImpl<Bar>()
Foo.fooInjectors[Foo::class.java] = InjectorImpl<Bar>()
}
}

Kotlin Type inference by inline generic function

I simplified the code where I reached the problem, so lets say I've got 2 generic interfaces:
interface Interface1<T>
interface Interface2<T>
It doesn't matter if they have any methods or not. Then I created inline generic function to create universal object, that implements all interfaces I need:
private inline fun <reified T> createValue() = object : Interface1<T>, Interface2<T> { }
And then I added property in class that initialized with this function. Now it's important to use automatic type inferring here:
private val testPropertyInt = createValue<Int>()
All this code will be compiled. And that's enough to raise VerifyError in constructor call. If I say what type this property should be there wouldn't be any error:
private val testPropertyInt: Interface1<Int> = createValue<Int>()
May be it can be usefull if I place full code here:
interface Interface1<T>
interface Interface2<T>
class KotlinBugTest {
private val testPropertyInt = createValue<Int>()
#Test
fun testBug() {
assertEquals(4, 2 + 2)
}
private inline fun <reified T> createValue() = object : Interface1<T>, Interface2<T> { }
}
And the question is:
Why can it be compiled though it can't work with that type in runtime? I posted an issue on JetBrains tracker, hope they will do something about that.

How to define an extension function for a companion object of a typealias?

I thought typealiases were the same as the original type, just a different name.
I figure typealiases have the same references as the original type.
typealias Celsius = Double
fun Double.Companion.foo() {} // Works
fun Celsius.Companion.foo() {} // Does not work
Here, Companion is accessible from Double but Celsius gives an unresolved reference error.
No, you can't access to the companion objects via typealias. One possible workaround to create one more typealias for concrete companion:
typealias CelsiusCompanion = Double.Companion
After that you can use it as following:
fun CelsiusCompanion.foo() {}
If you want to define an extension function, it is not possible as hluhovskyi already stated, but things are differently if you just want to invoke functions of a companion object.
There are two ways of accessing functions and properties within a companion object. You can either specify the access explicitely or implicitely. The implicit way works with a typealias the explicit one does not.
Consider this minimal example:
class ClassWithCompanion{
companion object {
fun sayHello() {
println("Hello")
}
}
}
typealias Alias = ClassWithCompanion
fun main(args: Array<String>) {
ClassWithCompanion.sayHello() // implicit
ClassWithCompanion.Companion.sayHello() // explicit
Alias.sayHello() // implicit (works)
Alias.Companion.test() // explicit (does not work)
}