Eve Methods
@self (see Classes). An extension method adds a method to a class from outside its body, in a module or an aspect, without changing the class. Code that does not belong to a class is written as functions (see Functions). This chapter is about extension methods: how they are declared, where they can be used, and why they are safe.
Extension methods
An extension method is declared at the level of a module or an aspect. Its first parameter is @self with the type of the class it extends; the other parameters follow. It is called like a method of that class: p.shift(1, 2).
Syntax:
** extension method: Class gets the method name
method name(@self: Class, parameters) is
** statements that use self
...
return;
Example:
The module geometry declares the class Point and extends it with the method shift. It exports both, so a driver that imports the module can create points and shift them:
# geometry: points and how to move them
module geometry is
export (Point, shift, distance);
class Point = {x, y :Real} <: Object;
** extension method: Point gets the method shift
method shift(@self: Point, dx, dy: Real) is
let self.x += dx;
let self.y += dy;
return;
** a function, not a method: it belongs to no object
function distance(a, b: Point) => (@result: Real) is
let result := sqrt((b.x - a.x)^2 + (b.y - a.y)^2);
return;
end geometry;
# use the extension method
driver move_points is
from "lib" use (geometry(*));
process main is
new p := Point(x: 1, y: 2); ** Point has no constructor: filled by name
p.shift(2, 3); ** the extension method
expect p.x == 3 and p.y == 5;
print distance(p, Point(x: 0, y: 0));
return;
end move_points;
Where an extension method can be used
- Inside the module or the aspect that declares it, always;
- In another script only when a module exports it,
export (shift);, and the script imports that module. An aspect can't export: its extension methods stay inside it; - A driver can declare extension methods too, for its own use.
Static, not monkey patching
Some languages let a program add or replace the methods of a class while it runs ("monkey patching"): the class changes for everybody, and a method can be replaced without the authors of the class knowing it. Eve extension methods are different. They are static:
- The class itself never changes. An extension method is resolved by the compiler, from the declarations and the imports of the script that calls it;
- Only the scripts that declare or import the extension see it. Two modules can extend the same class with different methods without any conflict, until one script imports both; then the import fails with a name conflict, as for any two members with the same name;
- An extension method can't hide or replace a method of the class: a method of the class with the same name and the same signature is a compile error. With another signature it is an overload (Version 0.4, see Overloading, D-150);
- An extension method sees only the
publicmembers of the class, like any other code outside the class: it can't reach the private or protected state.
So an extension method is safe: it adds behavior where it is imported, and nothing else in the program changes.
Unsafe methods
A method whose name ends with ! is an unsafe method: public method record!(@self) is … return;, called s.record!();. It changes shared state: the properties of its class, which all objects of the class share, or the variables of a module, through the functions of that module. Because it changes shared state, it is unsafe for parallel processing: an aspect that calls an unsafe method, directly or through other calls, can be applied but not started in a parallel group. A method without ! works on its own object and its parameters only: it may change self, its @ parameters, print or write files.
A method, like a function or a process, can release its resources with defer (see Defer). The parameters of methods follow the rules of all subprograms: defaults, varargs, named arguments and @ parameters (see Subprograms).
A method is not a value: Eve has no references to methods and no method type, so a method is never passed as a callback, stored or returned (see Functions in a class).
Method Chaining in Eve
Method chaining is an advanced programming technique available in Eve that allows developers to call multiple methods on the same object in a single statement. This can lead to more concise and readable code, especially when performing a series of operations on an object.
How Method Chaining Works
In method chaining, each method in the chain returns the object it was called on after performing its operation. In Eve such a method writes @self in its result list as well: => (@self) means "the result is the object itself", so there is nothing to assign. This allows the next method in the chain to be called on the same object.
Example of Method Chaining
class Number(:T) = {value: T} <: Object is
constructor(initialValue: T) => (@self) is
let self := Object();
let self.value := initialValue;
return;
public method add(@self, addend: T) => (@self) is
let self.value += addend;
return;
public method multiply(@self, factor: T) => (@self) is
let self.value *= factor;
return;
public method print(@self) => (@self) is
print "Number value: {self.value}";
return;
end Number;
# Usage
process main is
new num := Number(:i32)(10);
num.add(5).multiply(2).print();
return;
Benefits of Method Chaining
- More concise code
- Improved readability for sequences of operations
- Fluent interface design
Considerations
While method chaining can lead to more elegant code, it's important to use it judiciously. Very long chains can sometimes become difficult to read or debug. Developers should balance the benefits of conciseness with overall code clarity.
Implementing Method Chaining
To implement method chaining in Eve, developers need to:
- Write
@selfin the parameter list (the object it receives) and in the result list (the object it returns):method add(@self, x: T) => (@self) is - End the method with a plain
return;: the result is already the object - Ensure that the method performs its operation before returning
Remember, implementing method chaining is optional in Eve. Developers can choose to use traditional method calls if they prefer, or mix chained and non-chained methods as appropriate for their code structure.
Read next: Processing