Rust Structures Structure methods


Example

To declare methods on a struct (i.e., functions that can be called "on" the struct, or values of that struct type), create an impl block:

impl Foo {
    fn fiddle(&self) {
        // "self" refers to the value this method is being called on
        println!("fiddling {}", self.my_string);
    }
}

// ...
foo.fiddle(); // prints "fiddling hello"

&self here indicates an immutable reference to an instance of struct Foo is necessary to invoke the fiddle method. If we wanted to modify the instance (such as changing one of its fields), we would instead take an &mut self (i.e., a mutable reference):

impl Foo {
    fn tweak(&mut self, n: isize) {
        self.my_num = n;
    }
}

// ...
foo.tweak(43);
assert_eq!(foo.my_num, 43);

Finally, we could also use self (note the lack of an &) as the receiver. This requires the instance to be owned by the caller, and will cause the instance to be moved when calling the method. This can be useful if we wish to consume, destroy, or otherwise entirely transform an existing instance. One example of such a use-case is to provide "chaining" methods:

impl Foo {
    fn double(mut self) -> Self {
        self.my_num *= 2;
        self
    }
}

// ...
foo.my_num = 1;
assert_eq!(foo.double().double().my_num, 4);

Note that we also prefixed self with mut so that we can mutate self before returning it again. The return type of the double method also warrants some explanation. Self inside an impl block refers to the type that the impl applies to (in this case, Foo). Here, it is mostly a useful shorthand to avoid re-typing the signature of the type, but in traits, it can be used to refer to the underlying type that implements a particular trait.

To declare an associated method (commonly referred to as a "class method" in other languages) for a struct simply leave out the self argument. Such methods are called on the struct type itself, not on an instance of it:

impl Foo {
    fn new(b: bool, n: isize, s: String) -> Foo {
        Foo { my_bool: b, my_num: n, my_string: s }
    }
}

// ...
// :: is used to access associated members of the type
let x = Foo::new(false, 0, String::from("nil"));
assert_eq!(x.my_num, 0);

Note that structure methods can only be defined for types that were declared in the current module. Furthermore, as with fields, all structure methods are private by default, and can thus only be called by code in the same module. You can prefix definitions with the pub keyword to make them callable from elsewhere.