Allow extensions to `override` member functions in selected cases


#1

TL;DR
allow extensions to win over member functions on subclasses, if the member function is only declared on base class


I know that extensions can’t win over member functions, and I’m also aware of @HidesMembers(though I’m not fully sure why it was used on Map interface), but actually there is a safe use case for that

we all know(and love perhaps?) that ByteBuffer.flip() returns Buffer instead of ByteBuffer

val m=allocate(...)
// do something with m
consumeBuffer(m.flip()as ByteBuffer)

and yes, don’t use ByteBuffer is a solution for that, but why can’t we create a extension function to do that?

fun ByteBuffer.flip()=apply{flip()} // or maybe apply{(this as Buffer).flip()}

however there are some dangling concerns:
1) will this cause confusion since override can’t change a method’s return type?
2) casting ByteBuffer to Buffer will break this, since extensions are resolved statically
3) should we support overriding toString(), in case of fixing some suboptimal implementation?
4) one could always use another name like Array.contentToString(), ByteBuffer.flip1()

since I couldn’t solve these problems myself, I’m posting them here to see if anyone have better ideas

–EDIT–
for 1, there should be no problem, a subtype can change return type to a subtype, see NetworkChannel.bind(…)


#2

I think it would be too confusing. I see a chance for a static version of . which should look quite different so there is not any chance for confusion. E.g., .:.. So writing

consumeBuffer(m.:.flip())

Can only be a call of an extension function or a call of a companion function.


#3

Import extension using an alias, in such case there is no ambiguity.