Structures
Structures can hold multiple fields of multiple types.
struct Animal {
name: String,
legs: u32,
}
Instances of structures can be created, and modified:
let mut insect = Animal {
name: String::from("insect"),
legs: 12,
};
insect.legs = 6;
Builder function can be used, and we can use defaults for fields name to be as the variable names:
fn produce_6legs_animal(name: String) -> Animal {
return Animal {
name,
legs: 6,
};
}
fn main() {
let ant = produce_6legs_animal(String::from("ant"));
}
Move fields from another structure. Notice that move of values from structure means that some of the fields are no longer valid:
fn print_animal(animal: &Animal){
println!("the animal {} has {} legs", animal.name, animal.legs)
}
fn main() {
let caterpillar = Animal {
name: String::from("caterpillar"),
legs: 12,
};
print_animal(&caterpillar);
let butterfly = Animal {
legs: 6,
..caterpillar
};
print_animal(&butterfly);
// compile error - value borrowed here after partial move
print_animal(&caterpillar);
}
Unnamed struct can also be used. Notice the instance creation is using regular parenthesis:
struct Position(String, i32, i32);
fn main() {
let start = Position(String::from("start"), 0, 0);
}
Structs without any fields can also be used:
struct MyTrait;
fn main() {
let my_trait = MyTrait;
}
Moving on to Objects
Structures are used for object oriented design. Using structs and impl blocked we can create multiple constructors and methods. Notice that we can have multiple impl blocks.
struct Person {
name: String,
age: i32,
}
impl Person {
fn new_baby(name: String) -> Self {
return Person {
name,
age: 0,
};
}
fn is_very_old(&self) -> bool {
self.age > 120
}
fn is_older_than(&self, other: &Person) -> bool {
self.age > other.age
}
}
Using the objects is simple.
Again, to avoid move of ownership use pointers for structure when sending it as parameter.
fn main() {
let noah = Person {
name: String::from("Noam"),
age: 950,
};
let einstein = Person {
name: String::from("Einstein"),
age: 76,
};
let baby = Person::new_baby(String::from("Herman"));
let description = if noah.is_very_old() { "very old" } else { "young" };
println!("the person {:?} is {}", noah.name, description);
if noah.is_older_than(&einstein) {
println!("Noah is older than Einstein")
}
}
Debugging
let baby = Person::new_baby(String::from("Herman"));
println!("single line print {:?}", baby);
println!("multiple lines print {:#?}", baby);
dbg!(&baby);
single line print Person { name: "Herman", age: 0 }
multiple lines print Person {
name: "Herman",
age: 0,
}
[src/main.rs:26] &baby = Person {
name: "Herman",
age: 0,
}
Enums
use crate::Furniture::{Closet, Table};
#[derive(Debug)]
enum Furniture {
Chair,
Table,
Closet { doors: u32 },
}
impl Furniture {
fn open(&self) {
match self {
Closet { doors } => {
println!("open {doors} doors");
}
_ => (
println!("no need to open")
)
}
}
}
fn main() {
let chair = Furniture::Chair;
let closet = Closet { doors: 2 };
println!("{:?}", chair);
println!("{:?}", closet);
chair.open();
closet.open();
}
Option
fn square(i: Option<i32>) -> Option<i32> {
return match i {
Some(x) => Some(x * x),
None => None,
};
}
fn main() {
let two = Some(2);
let none = None;
// prints Some(4)
println!("{:?}", square(two));
// prints None
println!("{:?}", square(none));
}
if let Some(i) = two {
println!("the actual value of the option is {}", i)
}
No comments:
Post a Comment