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 many methods defined for the i32. 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 and functions.

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 global functions.

The type's namespace

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

Because methods belong to a type's namespace, this means different types can define methods having the same name, each doing something different (appropriate to its type). There is no confusion over which one to use, because use of a method by functions or methods external to the type is qualified implicitly (using the dot operator) or explicitly (using the double colon) by the desired type.

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 there is a requirement that same-named methods differ in their parameter definitions, either by type or by number of required 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 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. This means they get special handling in certain situations.

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:

Computed properties

It is possible to define a method as having two distinct get and set behaviors.

struct Counter
	count u32
	fn counter
		 get() {count += 1}
		 set(cnt) {count = cnt}

The get function is performed in most situations where the method is called. The set function is performed whenever the method is called on the left of an assignment. As a convenience, the parentheses can be avoided if the get definition has no parameters and the set has one.

mut x Count{0}
x.counter // 1 from get()
x.counter // 2
x.counter = 10 // sets
x.counter // 11

_