Use cases include GUIs and certain tree-like structures (ex. Servo’s DOM). In both cases, interfaces allow the type system to guarantee what it would otherwise not be able to. Servo is currently forced to use unsafe code to work around this.
Detailed design
Syntax
A class is declared as follows:
struct class X {
...
}
// OR
enum class X
...
}
// Here's how you extend another class
struct class Y : X {
...
}
// Same for enum-based classes
enum class Y : X {
...
}
The contextual keyword class is added. It is valid only after the keyword struct or enum.
Only single inheritance is supported.
Methods of a class can be declared virtual by placing the virtual contextual keyword before fn. To override a method, the override contextual keyword must be used in the same place.
Typing
Classes do not implement Sized. Therefore, only references can be used. A subclass reference can be cast to a superclass reference using the upcast method or the (new) :> operator.
In general, type inference in the presence of subtyping is difficult, so upcasting is not implicit.
What on earth does it mean to extend an enum class? The subenum can’t have more variants, because then the inherited methods from the parent would become partial.
Hm, I suppose the subclass could have fewer variants…?
So I have a lot of thoughts on this topic. =) I’ve not been able to find time to write down my latest, but I think the path I would like to see is roughly that we build on RFC 1546, which permits traits to have fields. Roughly speaking, traits would play the role of “abstract classes” or “interfaces” in OO terminology, and specialization would be used to handle inheritance.
Of those, the one on @aturon’s blog is probably most relevant to my current thoughts about traits and fields, since it describes how specialization works. But I think that the other articles are still interesting, and I’d like to see motion towards variants having their own types – eventually. (Or, more narrowly, towards making it more convenient to work with closed sets of classes, which is not the OO default.)
Well, ok, I simplified. It’s both open/closed and “size of the union” vs “size of the individual”. Note that that you can’t have “size of the union” with an open set of types.
IMO the principle difference is being able to pattern match on an enum (in other words, I primarily use enums to encapsulate data and traits to encapsulate functionality (more or less)). I think closed traits would still be useful and different from enums.
Interestingly enough, we do have closed traits, they’re just all private. So IMO, closing them would involve setting an “use” privacy that’s strictly larger than an “impl” privacy.
It almost sounds like our privacy system wants to be full-on ACL .
Loud NO to virtual methods. This was discussed years ago and the outcome was that creating parallel dynamic dispatch mechanism to trait objects is wrong direction.