Rust学习笔记
Rust编程语言入门教程课程笔记
Lecture 17: Object-Oriented Programming Features of Rust
src/main.rs
rust
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 runtime
fn draw(&self) {
// code to actually draw a select box
}
}
fn main() {
//Using Trait Objects That Allow for Values of Different Types
let 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 Pattern
let 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 Types
let 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
rust
//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 runtime
fn draw(&self) {
// code to actually draw a button
}
}
//Implementing an Object-Oriented Design Pattern
pub 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 state
self.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 Types
pub 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,
}
}
}