0

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?

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Dick Lucas
  • 12,289
  • 14
  • 49
  • 76
  • 5
    ... why would you want to do that? – user202729 Jan 08 '18 at 05:55
  • 1
    How do you intend to use those functions? Even theoretically? – voddan Jan 08 '18 at 07:25
  • 1
    @user202729 It has become abundantly clear that I wouldn't want to do that. The code snippet was a result of my misunderstanding on overloading. I appreciate everyone schooling me! – Dick Lucas Jan 09 '18 at 03:35
  • 1
    Some languages actually support this --- it's not as stupid a question as people are suggesting. See https://stackoverflow.com/questions/442026/function-overloading-by-return-type for a good writeup. – David Given Jul 24 '18 at 19:46

4 Answers4

2
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.

Rene
  • 5,730
  • 17
  • 20
  • 1
    I think the OP should reconsider if its really neccessary to have two variables/getters with the same name rather than using a solution like this – msrd0 Jan 08 '18 at 06:49
  • 1
    Thank you for actually answering the question as asked! – David Given Jul 24 '18 at 19:50
2

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:

  1. 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"
    
  2. 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")
    
  3. 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
msrd0
  • 7,816
  • 9
  • 47
  • 82
2

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.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
1

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.

s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
  • 1
    I don't think it is a good idea to use a Java doc source for a Kotlin problem, although both run on the JVM. – Willi Mentzel Jan 08 '18 at 08:18
  • It’s relevant since the rules also apply to Kotlin overloads – s1m0nw1 Jan 08 '18 at 08:28
  • 2
    Kotlin is a multiplatform language and has three implementations so far: JDK, JS and native. It has strong links to the JVM, but this is not a formal relationship. – Marko Topolnik Jan 08 '18 at 09:47
  • 1
    BTW there _is_ such a thing as the "[Kotlin Language Specification](https://jetbrains.github.io/kotlin-spec/#_name_and_overload_resolution)", only it's mostly TODOs at the moment. – Marko Topolnik Jan 08 '18 at 10:22
  • I don’t think that’s a reason for not referring to Java sources but it’s fine, removed it – s1m0nw1 Jan 08 '18 at 10:35