Eve Partials
Partials, Abstract Classes and Traits
A partial method is a method signature without a body, ended by ;. It says what an object can do, and leaves the implementation to another class. Three entities use partial methods. Each has a different job, so Eve names them separately:
| Entity | State | Methods | Created with "new" |
|---|---|---|---|
| Class | attributes and constructor | all implemented | yes |
| Abstract class | attributes and constructor | some partial | no, only a subclass constructor calls it |
| Trait | none | partial and provided | no, never has instances |
Abstract Class
A class that has at least one partial method is an abstract class. It can have attributes, a constructor and implemented methods, like any class, but it can not be instantiated. A subclass calls the abstract constructor by the name of the class, as the construction of its own constructor (see Construction). Inside a class body, object methods take @self without a type.
** abstract class: it has partial methods
class Shape = {name: String} <: Object is
constructor(name: String) => (@self) is
let self := Object();
let self.name := name;
return;
** implemented method, inherited by all shapes
public method getName(@self) => (@result: String) is
let result := self.name;
return;
** partial methods: the subclass must implement them
public method area(@self) => (@result: Real);
public method perimeter(@self) => (@result: Real);
end Shape;
class Circle = {radius: Real} <: Shape is
constructor(name: String, radius: Real) => (@self) is
let self := Shape(name); ** call the abstract constructor
let self.radius := radius;
return;
public method area(@self) => (@result: Real) is
let result := pi * self.radius * self.radius;
return;
public method perimeter(@self) => (@result: Real) is
let result := 2 * pi * self.radius;
return;
end Circle;
# Usage
process main is
new myCircle := Circle("Small Circle", 5);
print myCircle.getName(); ** inherited from Shape
print myCircle.area(); ** implemented by Circle
return;
A class that has a constructor must implement all the partial methods it inherits. A missing implementation is a compile error. It is never a null result at run time.
Traits
A trait is a set of behaviors that unrelated classes can share. It is declared with the keyword trait, and it closes with end. A trait is a container of methods only:
- it has no attributes, no properties, no constructor and no destructor, so it has no state and no instances;
- a required method is a partial method: the class that adopts the trait must implement it;
- a provided method has a body. It can call the required methods through
@self, and the class receives it for free; @selfhas no type: it is the class that adopts the trait;- a trait can be generic:
trait Comparable(:T) is.
** a trait: one required method and one provided method
trait Printable is
public method toString(@self) => (@result: String);
public method show(@self) is
print self.toString();
return;
end Printable;
** a class adopts traits in the inheritance list
class Circle = {radius: Real} <: (Shape, Printable) is
constructor(name: String, radius: Real) => (@self) is
let self := Shape(name);
let self.radius := radius;
return;
** implement the required methods of Shape and Printable
public method area(@self) => (@result: Real) is
let result := pi * self.radius * self.radius;
return;
public method perimeter(@self) => (@result: Real) is
let result := 2 * pi * self.radius;
return;
public method toString(@self) => (@result: String) is
let result := "Circle '" + self.getName() + "' with radius {self.radius}";
return;
end Circle;
# Usage
process main is
new myCircle := Circle("Small Circle", 5);
myCircle.show(); ** provided by the trait
new p: Printable := myCircle; ** a trait is also a type
p.show();
expect myCircle is Printable;
return;
Rules of the inheritance list
- A class has at most one superclass that carries state, and any number of traits. The superclass is optional (
Objectby default); - when a class and a trait define the same method, the method of the class wins;
- when two traits provide the same method, the class must implement the method itself, otherwise the compiler reports an error;
- a trait can be used as the type of a variable or a parameter, and tested with
is; - the
forloop uses the library traitIterable: a class that adopts it can be traversed.
Note: Eve has no "partial constructor". An object receives its state from the constructor of a class, and the traits add behavior only. This is why a class never inherits conflicting attributes from two parents.
Read next: Methods