Reputation: 12639
The below code
fun getValue(): Int {
return 42
}
fun getValue(): String {
return "Foo"
}
gives the following error:
Conflicting overloads: local final fun getValue(): String defined in main, local final fun getValue(): Int defined in main.
Is there any way to get around this without renaming one of the functions?
Upvotes: 0
Views: 2606
Reputation: 82007
How should the client specify which value he actually wants to get out of an instance of your class? These method names are ambiguous.
Look at the method signatures, only the return types differ, which is insufficient.
The rules for overloaded methods for Java also apply to Kotlin:
Overloaded methods are differentiated by the number and the type of the arguments passed into the method.
In your case, just give appropriate distinguishable names. You could also simply make those values properties if your class, no need to explicitly define default getters.
Upvotes: 1
Reputation: 29864
Short answer: No.
Long anser: A function signature consists of the name of that function and its parameter list.
Since the return type does not belong to the signature the compiler can not distinguish which function to use when you call:
val v = getValue() // should v be inferred to Int or String?
Not even specifying the return type explicitely solves the problem:
val v: Int = getValue()
because getValue()
is evaluated first without "knowing" where the return value will be assigned.
So, the best option you have is to choose a different name for one of the functions.
Upvotes: 2
Reputation: 8390
First of all, writing explicit getters in Kotlin is discouraged and it is suggested to use the following instead:
val value : Int get() = 42
val value : String get() = "Foo"
However, this still doesn't solve your problem. Since you did not give us any information why you need a declaration like this I can only give you some suggestions:
Find a more meaningful name for both variables other than value
. For example:
val intValue get() = 42 // note that you can omit :Int in this case
val textValue get() = "Foo"
If both values are bound together, you can use a Pair
:
val value get() = 42 to "Foo"
Now, you can access the two values via value.first
and value.second
. Note that to
is an infix function that creates a Pair
, so the above is equivalent to the more verbose notation
val value : Pair<Int, String> get() = Pair(42, "Foo")
If value
is something that's worth storing in its own object rather than using a Pair
, you could create your own data class for it:
data class MyData(val intVal : Int, val textVal : Text)
val value get() = MyData(42, "Foo")
With solutions 2 and 3 it will be possible to use a destructuring declaration, like this:
val (intVal, textVal) = value
Upvotes: 2
Reputation: 6258
inline fun <reified T> getValue(): T =
when (T::class) {
Int::class -> 42 as T
String::class -> "foo" as T
else -> throw IllegalArgumentException()
}
You could use a generic inline function with a reified type parameter. The given code block is inlined on each invocation.
The drawback is that the compiler can't check for wrong type parameters. You will get an IllegalArgumentException
.
Upvotes: 2