C+
Language · View as Markdown

Structs & methods

A struct defines data; an impl block defines the functions and methods that operate on it.

struct Point {
    x: i32,
    y: i32,
}

impl Point {
    // Associated function — no receiver. Called via `Point::new(...)`.
    fn new(x: i32, y: i32) -> Point {
        return Point { x: x, y: y };
    }

    // Instance method — receiver is `this`. Called via `p.translate(...)`.
    fn translate(ref this, dx: i32, dy: i32) {
        this.x = this.x +% dx;
        this.y = this.y +% dy;
    }

    fn magnitude_squared(this) -> i32 {
        return this.x *% this.x +% this.y *% this.y;
    }
}

fn main() -> i32 {
    var p: Point = Point::new(1, 2);
    p.translate(3, 4);
    return p.magnitude_squared();
}

Note the strict separation: :: reaches a type's associated items (Point::new), and . reaches an instance's methods (p.translate).

Struct literals

let x: i32 = 1;
let y: i32 = 2;
let p: Point = Point { x: x, y: y };

There is no field shorthand today; write every name: value pair explicitly.

Field visibility

Fields are public by default. To keep one private to the file, give it a leading underscore — the name itself is the marker, so privacy is always intentional:

struct Public {
    value: i32,                         // visible to other modules
    _internal: i32,                     // file-private
}

The three receiver forms

Methods take one of three receivers, which mirror the parameter markers. The name is always this; ref/take are the modifier:

impl Buf {
    fn read(this) { ... }                   // read-only borrow
    fn write(ref this) { ... }              // mutating method, writes back
    fn into_raw(take this) -> *u8 { ... }   // consumes the receiver
}

Bare this is the read-only borrow; ref this may mutate and the change propagates back to the caller (so the receiver place must be var); take this consumes the receiver. The full model, including how a bare receiver and a bare parameter are both read-only borrows, is in Ownership.