今天,我們來聊聊 Rust 的泛型(Generics)和 trait 概念。這些特性使得 Rust 能夠編寫高度抽象且可重用的程式碼,同時保持類型安全和高效率。
泛型允許我們編寫可以處理多種類型的程式碼,而不是為每種類型都寫一個特定的版本。
fn largest<T: PartialOrd>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}
fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest(&number_list);
println!("最大的數字是 {}", result);
let char_list = vec!['y', 'm', 'a', 'q'];
let result = largest(&char_list);
println!("最大的字符是 {}", result);
}
struct Point<T> {
x: T,
y: T,
}
impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}
fn main() {
let integer = Point { x: 5, y: 10 };
let float = Point { x: 1.0, y: 4.0 };
println!("x = {}", integer.x());
}
Trait 定義了一組方法,可以被不同的類型實現。它們類似於其他語言中的接口(Interface)。
trait Summary {
fn summarize(&self) -> String;
}
struct NewsArticle {
headline: String,
location: String,
author: String,
content: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}, by {} ({})", self.headline, self.author, self.location)
}
}
struct Tweet {
username: String,
content: String,
reply: bool,
retweet: bool,
}
impl Summary for Tweet {
fn summarize(&self) -> String {
format!("{}: {}", self.username, self.content)
}
}
fn main() {
let tweet = Tweet {
username: String::from("horse_ebooks"),
content: String::from("of course, as you probably already know, people"),
reply: false,
retweet: false,
};
println!("1 new tweet: {}", tweet.summarize());
}
fn notify(item: &impl Summary) {
println!("Breaking news! {}", item.summarize());
}
fn notify<T: Summary>(item: &T) {
println!("Breaking news! {}", item.summarize());
}
use std::fmt::Display;
fn notify<T: Summary + Display>(item: &T) {
println!("Breaking news! {}", item);
println!("Summary: {}", item.summarize());
}
fn some_function<T, U>(t: &T, u: &U) -> i32
where T: Display + Clone,
U: Clone + Debug
{
// 函數體
}
讓我們建立一個更複雜的範例,展示如何結合使用泛型和 trait:
use std::fmt::Display;
trait Drawable {
fn draw(&self);
}
struct Circle {
radius: f64,
}
struct Rectangle {
width: f64,
height: f64,
}
impl Drawable for Circle {
fn draw(&self) {
println!("Drawing a circle with radius {}", self.radius);
}
}
impl Drawable for Rectangle {
fn draw(&self) {
println!("Drawing a rectangle with width {} and height {}", self.width, self.height);
}
}
#[derive(Debug)]
struct Canvas<T: Drawable> {
shapes: Vec<T>,
}
impl<T: Drawable> Canvas<T> {
fn new() -> Self {
Canvas { shapes: Vec::new() }
}
fn add_shape(&mut self, shape: T) {
self.shapes.push(shape);
}
fn draw_all(&self) {
for shape in &self.shapes {
shape.draw();
}
}
}
fn print_info<T: Drawable + Display>(drawable: &T) {
println!("Info: {}", drawable);
drawable.draw();
}
fn main() {
let mut circle_canvas = Canvas::new();
circle_canvas.add_shape(Circle { radius: 5.0 });
circle_canvas.add_shape(Circle { radius: 10.0 });
let mut rectangle_canvas = Canvas::new();
rectangle_canvas.add_shape(Rectangle { width: 3.0, height: 4.0 });
rectangle_canvas.add_shape(Rectangle { width: 5.0, height: 6.0 });
println!("Drawing circles:");
circle_canvas.draw_all();
println!("\nDrawing rectangles:");
rectangle_canvas.draw_all();
}
這個例子展示了如何使用 trait 來定義共同行為(Drawable
),如何使用泛型來創建可以處理任何 Drawable
類型的 Canvas
,以及如何結合多個 trait bound。
明天,我們來聊 Rust 的並行程式設計特性,包括執行緒(threads)和消息傳遞機制。這些特性使得 Rust 能夠高效地處理並行任務,同時保持記憶體安全。