Methods add functional behavior to a defined type, offering capabilities consistent with and helpful for values of that type. For example, as mentioned earlier, `+` is one of several methods defined for the i32 type. It adds two integers together and returns the result.

Nearly every type supports the use of custom-defined methods: numbers, structs, indexed collections, variant types, interfaces, traits, slices, etc. Even allocators and permissions support methods. The only types that do not support their own customizeable methods are references, pointers, functions and static arrays (although any of these can do so when wrapped within a struct).

A method definition looks and behaves like a function definition: It has a name, named parameter(s), return value type(s), and a statement body. On this page we explore the ways that methods differ from functions.

The type's namespace

Functions typically belong to a global (module) namespace. By contrast, methods belong to a type's namespace. (Note: a type's named properties belong to the same namespace as its methods).

Since methods belong to a type's namespace, two different types can define a method with the same name, each doing something different and appropriate to its type. There is no confusion over which one to use, because use of a method is qualified implicitly (using the dot operator) by the type of the value it is applied to.

No such qualification is needed when a method calls another method in the same type; such a call looks exactly like a function call.

Multiple methods with the same name

Another difference between methods and functions is that a type may define more than one method of the same name. Once again, there is no confusion about which method to use, because same-named methods differ in their parameter definitions, either the number or type of its parameters. When a certain named method is used, Cone chooses the first method whose parameter definition matches the types and number of arguments passed to that method. Supporting multiple methods of the same name makes it convenient for a type to support a similar capability for a broad range of differently-typed values.

Self

A method's first parameter is always named self. The type specified for self must match the type the method is defined within, or else be a reference to a value of that type.

struct Point
  x f32
  y f32
  // a method that works on Point values...
  fn len(self) f32
    ((.x*.x)+(.y*.y)).sqrt()

fn test()
  imm pt = Point{3., 4.}
  imm c = pt.len() // use Point's 'len' method

A method's parameter need not specify the type if it is the same as the type the method is defined in. Similarly, when the type of self is the same as the method's type, which is typically the case, self need not even be declared in the method's parameter list. It will be inserted automatically.

Special-purpose Methods

A number of methods have a built-in role in Cone.

Constructors

A constructor method initializes a new value of the specified type. Constructors are useful when a type's initialization logic is more complex than simply populating fields or elements with values.

A type may define multiple constructor methods. By convention, the most commonly used constructor is called init. A type need not define any constructor method, as there are other ways to directly initialize a new value.

Like all other methods, a constructor declares self as its first parameter. In this case, self is a reference to an uninitialized memory location which can then be initialized. The new permission indicates this. A constructor always return self (otherwise, what's the point?).

struct Point
  x f32
  y f32
  fn init(new self &, x f32, y f32)
    .x, .y = x, y
	self

drop

Although it is not often needed, some types need the ability to perform some clean-up actions before the memory allocated for the value is freed. Often, this clean up involves releasing acquired resources. This clean-up activity should be performed within a method called drop.

Operator methods

Many operators are transformed into method calls. For instance, x+3 is treated as if it were: x.`+`(3) Because of this, a type need only implement the `+` method to make the + operator meaningful to that type. If you try to apply the + operator to a value whose type has not implemented the `+` method, a compiler error will result.

This applies to all the arithmetic, arithmetic assignment, and comparison operators as well as:

Implicit methods

Certain language constructs make use of specific methods under the covers:

set methods (Computed Properties)

By default, methods typically operate in "get" mode, invoked as part of an expression and often returning one or more values. However, it is possible for a method to be used on the left-hand side of an assignment. These are called "set" methods, and are declared by specifying set before fn.

struct Counter
	count u32
	fn counter() u32 {count += 1}          // a "getter" method
	set fn counter(cnt u32) {count = cnt}  // a "setter" method

The following example shows the use of this pair of get and set methods:

mut x = Counter{0}
x.counter // 1
x.counter // 2
x.counter = 10 // uses the "setter" to set the value
x.counter // 11

A "set" method can only be invoked to the left of an assignment operator. The value to be assigned is passed to the setter method as its last argument.

It is worth noting that with both the setter and getter method use, it is permissable to omit the parentheses when no additional arguments are passed. This makes the use of get and set methods look exactly like property access. This visual symmetry means that a type can migrate from making its properties public, to making them private, but still offering a compatible public interface of the same name using methods.

Static functions

Sometimes it makes sense to define a function as part of a type, because it plays a useful role in relationship to the type, even though it does not apply to a specific instance of the type. In such cases, precede the function definition with static to distinguish it from a method declaration.

struct Counter
	static fn factory() Counter
			Counter{0}

As with functions in a module namespace, a qualified name must be used to call the function:

mut cnt = Counter::factory()

_