Can we get rid of the `override` keyword? Do we re...
# language-proposals
x
Can we get rid of the
override
keyword? Do we really need it?
‘registration’ hides member of supertype ‘Vehicle’ and needs ‘override’ modifier
Couldn’t the compiler just assume it is
override
by default? If not, I don’t understand why do we need this ceremony
also
abstract
feels very verbose too sometimes.
Property must be initialized or be abstract
in a context of a sealed class, couldn’t the compiler assume it is
abstract
by default?
r
It prevents a) accidental overriding, and b) failing to override when you meant to do so. A classic from Java is to write
public boolean equals(Foo foo)
and think you have overridden equals when you haven't.
👍 4
Java introduced
@Overrides
specifically to help with that issue, and Scala also added an
override
keyword. My impression is it's fairly widely accepted that it's a Good Thing.
👍 4
👍🏻 1
x
b) failing to override when you meant to do so.
wouldn’t the compiler catch that for you?
r
Not if you were intending to override a non-abstract method like
equals
. Remember there are
open class
as well as `abstract`/`sealed`.
I have more sympathy on making
abstract
implicit on an abstract method on an abstract class. Requiring
abstract
feels a bit more arbitrary, particularly as both abstract classes and interfaces have methods with and without implementation, and interfaces don't require the
abstract
keyword (or Java's
default
one). I'd be interested in the reasoning for that.
👍 4
h
I really love it because it makes it clear, which function is actually implemented and overridden. Biggest "problem" is an abstract/open function which was removed later, but you still have the
@Override
annotated dead function in your code bais
e
Copy code
interface Foo {
   fun foo() 

   fun bar() { print("hello bar") }
}

class FooImpl() : Foo {
   // this doesn't override anything, but implements it
   // yet, we define this as an override...
   override fun foo() { print("hello") } 

   // this actually overrides the behaviour of Foo.bar()    
   override fun bar() { print("hello fooimpl") }
}
r
It doesn't bother me particularly that
override
means "implements or overrides". The important bit is that it allows the compiler to guarantee that the signature is defined on a supertype (and its absence allows the compiler to guarantee that the signature is not defined on a supertype). Is there a better short term that conveys that?
e
Yeah, doesn’t bother me either, but this thread just made me realize this explicitly. I think it’s good that a single keyword can be used for both purposes - and from the implementor’s point of view, there’s no difference, it’s just about the compiler.
k
On the subject of overrides, I note that if we implement two interfaces that have the same named function, we can only override that function once. By contrast, other languages, such as C#, allow something like this:
Copy code
interface Ia {
    fun foo()
}

interface Ib {
    fun foo()
}

class C : Ia, Ib {
    override fun Ia.foo() {  // Not valid Kotlin
        println("a")
    }

    override fun Ib.foo() {  // Not valid Kotlin
        println("b")
    }
}
Kotlin inherits Java's behaviour with respect to interfaces. This means that we can only implement two interfaces with the same-named function if that function has equivalent meaning between the two interfaces. Sometimes, two interfaces can have two functions that have a totally different intention but their names match purely by coincidence. C# allows us to write different implementations for each such function. In Kotlin, we need to do it in a roundabout way, e.g. by inserting an adaptor interface between one of the interfaces and the implementing class.
e
given that Kotlin compiles to JVM bytecode and is compatible with Java's object model, there's no way around that
overload lookups on JVM are purely by name and signature, so Kotlin would have to either mangle the name of all interface functions or add hidden parameters, both of which lose Java compatibility