50.10.1Rectangle area¶
The rectangle structure has two fields width and height:
struct Rect {
width: u32,
height: u32,
}The area method takes a reference on self and does its computing:
impl Rect {
fn area(&self) -> u32 {
self.width * self.height
}
}Here is a call to area() on an example of instance:
let rect = Rect { width: 10, height: 20 };
rect.area()20050.10.2Rectangle & square¶
The rectangle structure may be implemented as following, using 32-bit floats:
struct Rect {
width: f32,
height: f32,
}The default constructor takes both the width and the height to
build a new Rect object:
impl Rect {
fn new(width: f32, height: f32) -> Self {
Self {
width,
height,
}
}
}The square() constructor takes only one f32 value as argument. It is
used to set both width and height:
impl Rect {
fn square(sz: f32) -> Self {
Self {
width: sz,
height: sz,
}
}
}Here is an example of building a regular rectangle:
let a_rect = Rect::new(5.0, 4.5);
(a_rect.width, a_rect.height)(5.0, 4.5)The same for a square:
let a_square = Rect::square(10.0);
(a_square.width, a_square.height)(10.0, 10.0)50.10.3Postal mail¶
Here is a possible structure for modelling a postal mail:
struct Mail {
recipient: &'static str,
sender: &'static str,
weight: f32,
priority: bool,
}We implement the new() constructor and the builder setters for
weight and priority:
impl Mail {
fn new(recipient: &'static str, sender: &'static str) -> Self {
Self {
recipient,
sender,
weight: 20.0,
priority: false,
}
}
fn with_weight(mut self, weight: f32) -> Self {
self.weight = weight;
self
}
fn with_priority(mut self, priority: bool) -> Self {
self.priority = priority;
self
}
}An example of Mail instance:
let mail = Mail::new(
"RMN 254 rue de Bercy 75577 Paris Cedex 12",
"Marcel Dupond 3 rue de Bruxelles 59000 Lille")
.with_weight(100.0)
.with_priority(true);The content of the instance:
(mail.recipient, mail.sender, mail.weight, mail.priority)("RMN 254 rue de Bercy 75577 Paris Cedex 12", "Marcel Dupond 3 rue de Bruxelles 59000 Lille", 100.0, true)50.10.4Book¶
We define the Book structure, its constructor and three access
functions to access the values of the three fields:
struct Book {
title: &'static str,
author: &'static str,
year: i16,
}
impl Book {
fn new(title: &'static str, author: &'static str, year: i16) -> Self {
Self {
title,
author,
year,
}
}
fn title(&self) -> &'static str {
self.title
}
fn author(&self) -> &'static str {
self.author
}
fn year(&self) -> i16 {
self.year
}
}Here is an example of usage of the constructor and the access functions:
let book = Book::new("Robinson Crusoe", "Daniel Defoe", 1719);
(book.title(), book.author(), book.year())("Robinson Crusoe", "Daniel Defoe", 1719)In both the constructor function and the access functions, the idea is to encapsulate the construction and the access. If later we need to run code during construction or access, it will be easy inserted inside the function.
50.10.5Square area¶
We define a struct named Square that we can define be either giving
the area or the side length. From one value the constructor function
computes the other, leaving the original value untouched. This example
shows how we can force to run the same computation for each constructed
object:
struct Square {
a: f32,
area: f32,
}
impl Square {
fn new(mut a: f32, mut area: f32) -> Self {
if a < 0.0 {
a = area.sqrt();
}
if area < 0.0 {
area = a * a;
}
Self {
a,
area,
}
}
fn a(&self) -> f32 {
self.a
}
fn area(&self) -> f32 {
self.area
}
}Excepted the representation error, the original value of the area of the following square is untouched, while the re-computed area propagates an error:
let c = Square::new(-1.0, 1.0001);
println!("a={:.10}, a*a={:.10}", c.a(), c.area());
println!("a={:.10}, a*a={:.10} (recomputed)", c.a(), c.a() * c.a());a=1.0000499487, a*a=1.0001000166
a=1.0000499487, a*a=1.0000998974 (recomputed)