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.

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.

Methods with pre-defined roles

A number of method names have an important built-in role in various Cone features.

Operator methods

Many operators are implemented as method calls. For instance, x+3 is treated as if it were: x.`+`(3) A type need only implement the `+` method to make the + operator meaningful to values of that type. If a program tries to apply the + operator to a value whose type has not implemented the `+` method, a compiler error results.

This principle applies to all the arithmetic, arithmetic assignment, and comparison operators. It also applies to:

Implicit methods

Various language constructs call certain methods under the covers:

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()

_