Rust学习笔记
Rust编程语言入门教程课程笔记
参考教材: The Rust Programming Language (by Steve Klabnik and Carol Nichols, with contributions from the Rust Community)
Lecture 17: Object-Oriented Programming Features of Rust
src/main.rs
use oop::Draw;
use oop::{Button, Screen};use oop::Post;
use oop::Post2;struct SelectBox {width: u32,height: u32,options: Vec<String>,
}impl Draw for SelectBox {//The trait object is then responsible for calling the draw method at runtimefn draw(&self) {// code to actually draw a select box}
}fn main() {//Using Trait Objects That Allow for Values of Different Typeslet screen = Screen {components: vec![Box::new(SelectBox {width: 75,height: 10,options: vec![String::from("Yes"),String::from("Maybe"),String::from("No"),],}),Box::new(Button {width: 50,height: 10,label: String::from("OK"),}),],};screen.run();//Implementing an Object-Oriented Design Patternlet mut post = Post::new();post.add_text("I ate a salad for lunch today");assert_eq!("", post.content());post.request_review();assert_eq!("", post.content());//Using Trait Objects That Allow for Values of Different Typeslet mut post = Post2::new();post.add_text("I ate a salad for lunch today");let post = post.request_review();let post = post.approve();assert_eq!("I ate a salad for lunch today", post.content());
}
src/lib.rs
//Object-Oriented Programming: Object, Encapsulation, Inheritance, Polymorphism//Encapsulation: A unit of code that hides its implementation details and exposes a public API.
pub struct AveragedCollection {list: Vec<i32>,average: f64,
}impl AveragedCollection {pub fn add(&mut self, value: i32) {self.list.push(value);self.update_average();}pub fn remove(&mut self) -> Option<i32> {let result = self.list.pop();match result {Some(value) => {self.update_average();Some(value)}None => None,}}pub fn average(&self) -> f64 {self.average}fn update_average(&mut self) {let total: i32 = self.list.iter().sum();self.average = total as f64 / self.list.len() as f64;}
}//Using Trait Objects That Allow for Values of Different Types
pub trait Draw {fn draw(&self);
}pub struct Screen {pub components: Vec<Box<dyn Draw>>, //dyn: dynamic dispatch
}impl Screen {pub fn run(&self) {for component in self.components.iter() {component.draw();}}
}//Implementing the Trait
pub struct Button {pub width: u32,pub height: u32,pub label: String,
}impl Draw for Button {//The trait object is then responsible for calling the draw method at runtimefn draw(&self) {// code to actually draw a button}
}//Implementing an Object-Oriented Design Patternpub struct Post{state: Option<Box<dyn State>>,content: String,
}impl Post {pub fn new() -> Post {Post {state: Some(Box::new(Draft{})),content: String::new(),}}pub fn add_text(&mut self, text: &str){self.content.push_str(text);}pub fn content(&self) -> &str{self.state.as_ref().unwrap().content(self)}pub fn request_review(&mut self){if let Some(s) = self.state.take(){//take() method to move the Some value out of stateself.state = Some(s.request_review());}}pub fn approve(&mut self){if let Some(s) = self.state.take(){self.state = Some(s.approve());}}
}trait State{fn request_review(self: Box<Self>) -> Box<dyn State>;fn approve(self: Box<Self>) -> Box<dyn State>;fn content<'a>(&self, post: &'a Post) -> &'a str{""}
}struct Draft{}impl State for Draft{fn request_review(self: Box<Self>) -> Box<dyn State>{Box::new(PendingReview{})}fn approve(self: Box<Self>) -> Box<dyn State>{self}
}struct PendingReview{}impl State for PendingReview{fn request_review(self: Box<Self>) -> Box<dyn State>{self}fn approve(self: Box<Self>) -> Box<dyn State>{Box::new(Published{})}
} struct Published{}impl State for Published{fn request_review(self: Box<Self>) -> Box<dyn State>{self}fn approve(self: Box<Self>) -> Box<dyn State>{self}fn content<'a>(&self, post: &'a Post) -> &'a str{&post.content}
}//Using Trait Objects That Allow for Values of Different Typespub struct Post2{content: String,
}pub struct DraftPost{content: String,
}impl Post2{pub fn new() -> DraftPost{DraftPost{content: String::new(),}}pub fn content(&self) -> &str{&self.content}
}impl DraftPost{pub fn add_text(&mut self, text: &str){self.content.push_str(text);}pub fn request_review(self) -> PendingReviewPost{PendingReviewPost{content: self.content,}}
}pub struct PendingReviewPost{content: String,
}impl PendingReviewPost{pub fn approve(self) -> Post2{Post2{content: self.content,}}
}