Rust中的特型和范型
Rust中的特型Trait类似于Java中的接口Interface或抽象类Abstract Class,有些不同的是,Trait可以用于任意结构,包括系统内置结构体或自定义的结构体。
要求:创建一个泛型数据容器 GenericContainer
- Processable Trait:
- 定义一个名为 process(&self) -> String 的 Trait,要求实现者返回一个表示其处理结果的字符串。
- 为 i32 实现 Processable Trait(例如,返回 “Processed integer: N”)。
- 为 String 实现 Processable Trait(例如,返回 “Processed string: ‘S’“)。
- 定义一个简单的 Point 结构体(包含 x: i32, y: i32),并为其实现 Processable Trait(例如,返回 “Processed point: (X, Y)”)。
- GenericContainer
结构体: - 应包含一个 Vec
来存储数据。 - 实现一个 new() 关联函数来创建实例。
- 实现一个 add_item(item: T) 方法来向容器中添加元素。
- 实现一个 process_all_items(&self) -> Vec
方法。这个方法应遍历容器中的所有元素,并为每个元素调用其 process() 方法,然后将所有结果字符串收集到一个 Vec 中返回。注意: 只有当 T 类型实现了 Processable Trait 时,才能调用此方法。
- 应包含一个 Vec
- 测试:
- 创建 GenericContainer
实例,添加一些整数,然后处理并打印结果。 - 创建 GenericContainer
实例,添加一些字符串,然后处理并打印结果。 - 创建 GenericContainer
实例,添加一些点,然后处理并打印结果。
- 创建 GenericContainer
下面是例子代码,需要注意的是下面process_all_items方法,为了能够达到每个x都有x.process()的方法,impl
pub trait Processable{
fn process(&self) -> String;
}
impl Processable for i32 {
fn process(&self) -> String {
format!("Processed integer: {}", &self)
}
}
impl Processable for String {
fn process(&self) -> String {
format!("Processed String: {}", &self)
}
}
pub struct Point {
x: i32,
y: i32,
}
impl Processable for Point {
fn process(&self) -> String {
format!("Processed Point({}, {})", self.x, self.y)
}
}
pub struct GenericContainer<T> {
list: Vec<T>
}
impl<T: Processable> GenericContainer<T> { // 注意T的类型的写法
pub fn new() -> Self {
GenericContainer { list: Vec::new() }
}
pub fn add_item(&mut self, item: T) {
self.list.push(item);
}
pub fn process_all_items(&self) -> Vec<String> {
self.list.iter().map(|x| x.process()).collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_process_point() {
let p = Point{
x: 100,
y: -50,
};
assert_eq!(p.process(), "Processed Point(100, -50)");
}
#[test]
fn test_process_i32() {
let i = 100;
assert_eq!(i.process(), "Processed integer: 100");
}
#[test]
fn test_process_string() {
let hello = "hello,world".to_string();
assert_eq!(hello.process(), "Processed String: hello,world");
}
#[test]
fn test_container_i32() {
let mut c = GenericContainer::new();
for i in 0..2 {
c.add_item(i);
}
let result = c.process_all_items();
assert_eq!(
format!("{:?}", result),
"[\"Processed integer: 0\", \"Processed integer: 1\"]"
);
}
#[test]
fn test_container_string() {
let mut c = GenericContainer::new();
c.add_item("hello".to_string());
c.add_item("there".to_string());
let result = c.process_all_items();
assert_eq!(
format!("{:?}", result),
"[\"Processed String: hello\", \"Processed String: there\"]"
);
}
#[test]
fn test_container_point() {
let mut c = GenericContainer::new();
c.add_item(Point{x:1, y:2});
c.add_item(Point{x:0, y:-2});
let result = c.process_all_items();
assert_eq!(
format!("{:?}", result),
"[\"Processed Point(1, 2)\", \"Processed Point(0, -2)\"]"
);
}
}