Rust by Example - страница 24
>
>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Methods are functions attached to objects. These methods have access to the data of the object and its other methods via the self keyword. Methods are defined under an impl block.
>struct Point {
>x: f64,
>y: f64,
>}
>// Implementation block, all `Point` methods go in here
>impl Point {
>// This is a static method
>// Static methods don't need to be called by an instance
>// These methods are generally used as constructors
>fn origin() -> Point {
>Point { x: 0.0, y: 0.0 }
>}
>// Another static method, taking two arguments:
>fn new(x: f64, y: f64) -> Point {
>Point { x: x, y: y }
>}
>}
>struct Rectangle {
>p1: Point,
>p2: Point,
>}
>impl Rectangle {
>// This is an instance method
>// `&self` is sugar for `self: &Self`, where `Self` is the type of the
>// caller object. In this case `Self` = `Rectangle`
>fn area(&self) -> f64 {
>// `self` gives access to the struct fields via the dot operator
>let Point { x: x1, y: y1 } = self.p1;
>let Point { x: x2, y: y2 } = self.p2;
>// `abs` is a `f64` method that returns the absolute value of the
>// caller
>((x1 - x2) * (y1 - y2)).abs()
>}
>fn perimeter(&self) -> f64 {
>let Point { x: x1, y: y1 } = self.p1;
>let Point { x: x2, y: y2 } = self.p2;
>2.0 * ((x1 - x2).abs() + (y1 - y2).abs())
>}
>// This method requires the caller object to be mutable
>// `&mut self` desugars to `self: &mut Self`
>fn translate(&mut self, x: f64, y: f64) {
>self.p1.x += x;
>self.p2.x += x;
>self.p1.y += y;
>self.p2.y += y;
>}
>}
>// `Pair` owns resources: two heap allocated integers
>struct Pair(Box
>impl Pair {
>// This method "consumes" the resources of the caller object
>// `self` desugars to `self: Self`
>fn destroy(self) {
>// Destructure `self`
>let Pair(first, second) = self;
>println!("Destroying Pair({}, {})", first, second);
>// `first` and `second` go out of scope and get freed
>}
>}
>fn main() {
>let rectangle = Rectangle {
>// Static methods are called using double colons
>p1: Point::origin(),
>p2: Point::new(3.0, 4.0),
>};
>// Instance methods are called using the dot operator
>// Note that the first argument `&self` is implicitly passed, i.e.
>// `rectangle.perimeter()` === `Rectangle::perimeter(&rectangle)`
>println!("Rectangle perimeter: {}", rectangle.perimeter());
>println!("Rectangle area: {}", rectangle.area());
>let mut square = Rectangle {
>p1: Point::origin(),
>p2: Point::new(1.0, 1.0),
>};
>// Error! `rectangle` is immutable, but this method requires a mutable
>// object
>//rectangle.translate(1.0, 0.0);
>// TODO ^ Try uncommenting this line
>// Okay! Mutable objects can call mutable methods
>square.translate(1.0, 1.0);
>let pair = Pair(Box::new(1), Box::new(2));
>pair.destroy();
>// Error! Previous `destroy` call "consumed" `pair`
>//pair.destroy();
>// TODO ^ Try uncommenting this line
>}
>הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Closures are functions that can capture the enclosing environment. For example, a closure that captures the x variable:
>|val| val + x
The syntax and capabilities of closures make them very convenient for on the fly usage. Calling a closure is exactly like calling a function. However, both input and return types can be inferred and input variable names must be specified.
Other characteristics of closures include:
• using || instead of () around input variables.
• optional body delimination ({}) for a single expression (mandatory otherwise).
• the ability to capture the outer environment variables.