I'm attempting to have two implementations of an interface one of which inherits the default values from the other implementation, but overrides one.
Here's an example that shows the behavior:
fun main() {
println(Bottom.value) // prints: bottom
println(Bottom.determineValue()) // prints: middle
}
interface Top {
val value: String
val otherValue: String
fun determineValue() = value
}
object Middle : Top {
override val value = "middle"
override val otherValue = "something else"
}
object Bottom : Top by Middle {
override val value = "bottom"
}
I'm getting unexpected behavior in that, when the property value
is used in outside of the Bottom
implementation, it returns the value from Middle
instead of Bottom
.
If someone has more insight on why this is occurring, I'd appreciate any explanation
CodePudding user response:
This is expected behavior that is described in the Kotlin documentation of the delegate functionality.
Note, however, that members overridden in this way do not get called from the members of the delegate object, which can only access its own implementations of the interface members
An implementation being used as a delegate has no knowledge that it is being used as a delegate and therefore cannot and will not access members of that other class. Any of its implementations that call its other members will not use the overridden versions that are in the class that are using it as a delegate. There is no way to get around this problem except to re-implement the feature:
object Bottom : Top by Middle {
override val value = "bottom"
override fun determineValue() = value
}
CodePudding user response:
To illustrate Tenfour04's answer:
There are two objects here: Bottom
and Middle
(both implementing the Top
interface).
The call path looks like this:
Bottom.determineValue()
│ (by delegation)
│
└──────────→ Middle.determineValue()
┌─────────────┘ (defined in Top)
│
└→ Middle.value
Delegation works by forwarding all (non-overridden) calls to the delegate. Here Bottom
doesn't override determineValue()
, so Bottom
.determineValue()
calls its delegate, Middle
.determineValue()
, which returns its own value
(because it knows nothing about Bottom
).