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.