Reputation: 23091
I have a Java class (which I cannot edit, because it's auto-generated by Thrift) defined like this:
public class TheirException extends Throwable {
public String message;
public TheirException(String message) {
this.message = message;
}
public String getMessage() {
return this.message;
}
}
However, if I try to get message
from Kotlin, getMessage()
is not available and produces an Unresolved reference
error. Trying to use the message
field produces the following error:
Error:(470, 30) Kotlin: Overload resolution ambiguity:
public final var message: String! defined in com.example.TheirException
public open val message: String? defined in com.example.TheirException
However, if I instead do:
(exception as Throwable).message
it resolves fine.
Why is casting to Throwable
necessary here, why is getMessage()
not available, and what is causing the ambiguity?
Upvotes: 5
Views: 648
Reputation: 732
The ambiguity is caused by the fact that message
is public. Kotlin translates every getter to a property even if there are no backing fields. If you add another function to this class:
public String getSecondMessage() {
return "second message"; // Note that this getter does not rely on a field
}
You can access it like this in Kotlin:
TheirException("message").secondMessage
If message
is public and there is a getMessage()
function Kotlin creates 2 getters and on the call site you newer know which to use. In your example the 2 getters would have the same behavior but that is not always the case.
When you cast your class to a Throwable
you explicitly tell the compiler that this class has the signature of a Throwable
, which means you define that there should be only one message
getter, this resolves the ambiguity. Note here that Kotlin has its own definition of a Throwable
(this will be important later).
Now you might ask why there is no getMessage()
function. This is because you are casting to Throwable
and not java.lang.Throwable
. The Kotlin definition of Throwable
has no getMessage()
Upvotes: 2