We unveiled this live at the Modular community meeting last night: default methods can now be defined on traits! This lets a trait define an implementation of a method that is provided to all conforming structs. These default methods can be explicitly overridden in conforming structs, as needed.
As an example:
# Any struct conforming to EqualityComparable now only needs to define one of
# __ne__ ~or~ __eq__ and will get a definition of the other with no
# additional code!
# For instance:
trait EqualityComparable:
fn __eq__(self, other: Self) -> Bool:
...
fn __ne__(self, other: Self) -> Bool:
return not self.__eq__(other)
@value
struct Point(EqualityComparable):
var x: Int
var y: Int
fn __eq__(self, other: Self) -> Bool:
# Since __eq__ is implemented we now get __ne__ defined for free!
return self.x == other.x and self.y == other.y
# Defaulted methods can also be overriden if we want different behavior.
# fn __ne__(self, other: Self) -> Bool:
# return self.x != other.x or self.y != other.y
Currently a trait method is considered to be non-defaulted if the first thing in it’s body is either a ‘…’ or a ‘pass’. In the future, only ‘…’ will mark a trait method as not defaulted. For example:
trait Foo:
# Either of the following are non-defaulted
# fn foo(self):
# ...
#
# fn foo(self):
# pass
# While this is not:
fn foo(self):
print("Foo.foo")
We’re excited to see how much code we can clean up as a result of this new feature. Check out all that red in this commit due to being able to define __ne__ in terms of __eq__ within EqualityComparable. And that’s just one case!