Trait 系统 (Trait System)
概述
Valkyrie 的 trait 系统提供了强大的抽象机制,支持接口定义、默认实现、多重继承和匿名 trait。Trait 系统是 Valkyrie 面向对象编程的核心组成部分。
基本 Trait 定义
简单 Trait
valkyrie
trait Display {
fmt(self) -> String
}
trait Clone {
clone(self) -> Self
}
trait Debug {
debug_fmt(self) -> String {
# 默认实现
@format("{}@{:p}", self.type_name(), &self)
}
}带关联类型的 Trait
valkyrie
trait Iterator {
type Item
next(mut self) -> Option<Self::Item>
collect<C: FromIterator<Self::Item>>(self) -> C {
C::from_iter(self)
}
}
trait FromIterator<T> {
from_iter<I: Iterator<Item = T>>(iter: I) -> Self
}带约束的 Trait
valkyrie
trait PartialEq<Rhs = Self> {
eq(self, other: &Rhs) -> bool
ne(self, other: &Rhs) -> bool {
!self.eq(other)
}
}
trait Ord: PartialEq + PartialOrd {
cmp(self, other: &Self) -> Ordering
}Trait 实现
基本实现
valkyrie
class Point {
x: f64,
y: f64,
}
imply Display for Point {
fmt(self) -> String {
@format("Point({}, {})", self.x, self.y)
}
}
imply Clone for Point {
clone(self) -> Self {
new Point { x: self.x, y: self.y }
}
}泛型实现
valkyrie
impl<T: Display> Display for Vector<T> {
fmt(self) -> String {
let items = self.iter()
.map({ $item.fmt() })
.collect::<Vector<String>>()
.join(", ")
@format("[{}]", items)
}
}
impl<T: Clone> Clone for Vector<T> {
clone(self) -> Self {
self.iter().map({ $item.clone() }).collect()
}
}条件实现
valkyrie
impl<T: PartialEq> PartialEq for Vector<T> {
eq(self, other: &Self) -> bool {
self.len() == other.len() &&
self.iter().zip(other.iter()).all({ $a.eq($b) })
}
}匿名 Trait
Valkyrie 支持匿名 trait,可以在函数参数中直接定义:
valkyrie
# 匿名 trait 作为参数
micro process_drawable(drawable: ftrait {
draw(self)
get_bounds(self) -> Rectangle
}) {
let bounds = drawable.get_bounds()
println("Drawing object with bounds: {}", bounds)
drawable.draw()
}
# 使用匿名 trait
let circle = class {
radius: f64,
draw(self) {
println("Drawing circle with radius {}", self.radius)
}
get_bounds(self) -> Rectangle {
Rectangle::new(-self.radius, -self.radius,
self.radius * 2, self.radius * 2)
}
}
process_drawable(new circle { radius: 5.0 })匿名 Trait 继承
valkyrie
# 继承现有 trait 的匿名 trait
micro handle_serializable(obj: ftrait(Display, Clone) {
Encode(self) -> String
}) {
println("Object: {}", obj.fmt())
let cloned = obj.clone()
let Encoded = obj.Encode()
println("Encoded: {}", Encoded)
}Trait 对象
动态分发
valkyrie
trait Animal {
make_sound(self)
name(self) -> String
}
class Dog {
name: String,
}
imply Animal for Dog {
make_sound(self) {
println("Woof!")
}
name(self) -> String {
self.name.clone()
}
}
class Cat {
name: String,
}
imply Animal for Cat {
make_sound(self) {
println("Meow!")
}
name(self) -> String {
self.name.clone()
}
}
# 使用 trait 对象
let animals: Vector<Box<dyn Animal>> = vec![
Box::new(new Dog { name: "Buddy" }),
Box::new(new Cat { name: "Whiskers" }),
]
for animal in animals {
println("{} says:", animal.name())
animal.make_sound()
}Trait 对象安全
valkyrie
# 对象安全的 trait
trait Draw {
draw(self) # 接收 self,对象安全
}
# 非对象安全的 trait
trait Clone {
clone(self) -> Self # 返回 Self,非对象安全
}
# 使用 where 子句限制
trait Container {
type Item
get(self, index: usize) -> Option<&Self::Item>
# 只有当 Self::Item 实现了 Display 时才能调用
display_item(self, index: usize)
where Self::Item: Display {
if let Some(item) = self.get(index) {
println("{}", item.fmt())
}
}
}高级特性
关联常量
valkyrie
trait MathConstants {
const PI: f64 = 3.14159265359
const E: f64 = 2.71828182846
circle_area(radius: f64) -> f64 {
Self::PI * radius * radius
}
}
class Calculator {}
imply MathConstants for Calculator {}
let area = Calculator::circle_area(5.0)高阶 Trait 边界
valkyrie
# 高阶 trait 边界
micro map_closure<F, T, U>(items: Vector<T>, f: F) -> Vector<U>
where
F: Fn(&T) -> U,
{
items.iter().map(f).collect()
}
# 使用示例
let numbers = vec![1, 2, 3, 4, 5]
let doubled = map_closure(numbers, { $x * 2 })Trait 别名
valkyrie
# 定义 trait 别名
trait Printable = Display + Debug + Clone
# 使用 trait 别名
micro print_info<T: Printable>(item: T) {
println("Display: {}", item.fmt())
println("Debug: {}", item.debug_fmt())
let cloned = item.clone()
println("Cloned: {}", cloned.fmt())
}派生宏
Valkyrie 提供了自动派生常用 trait 的宏:
valkyrie
↯derive(Debug, Clone, PartialEq, Eq, Hash)
class User {
id: u64,
name: String,
email: String,
}
↯derive(Display)
class Point {
x: f64,
y: f64,
}
# 自定义派生行为
↯derive(Debug, Clone)
↯derive_display(format = "User({})", field = "name")
class SimpleUser {
name: String,
internal_id: u64, # 不会在 Display 中显示
}最佳实践
1. Trait 设计原则
valkyrie
# 好的设计:单一职责
trait Readable {
read(self, buffer: &mut [u8]) -> Result<usize, Error>
}
trait Writable {
write(self, data: &[u8]) -> Result<usize, Error>
}
# 组合使用
trait ReadWrite: Readable + Writable {}
# 避免:过于复杂的 trait
# trait FileOperations {
# read(...) -> ...
# write(...) -> ...
# seek(...) -> ...
# metadata(...) -> ...
# permissions(...) -> ...
# }2. 使用关联类型 vs 泛型参数
valkyrie
# 使用关联类型:每个类型只有一个实现
trait Iterator {
type Item
next(mut self) -> Option<Self::Item>
}
# 使用泛型参数:可以有多个实现
trait From<T> {
from(value: T) -> Self
}
# String 可以从多种类型转换
imply From<&str> for String { ... }
imply From<char> for String { ... }
imply From<Vector<char>> for String { ... }3. 错误处理
valkyrie
trait TryFrom<T> {
type Error
try_from(value: T) -> Result<Self, Self::Error>
}
trait TryInto<T> {
type Error
try_into(self) -> Result<T, Self::Error>
}
# 自动实现
impl<T, U> TryInto<U> for T
where U: TryFrom<T> {
type Error = U::Error
try_into(self) -> Result<U, Self::Error> {
U::try_from(self)
}
}总结
Valkyrie 的 trait 系统提供了:
- 灵活的抽象:通过 trait 定义行为接口
- 代码复用:通过默认实现和泛型
- 类型安全:编译时检查 trait 边界
- 动态分发:通过 trait 对象支持运行时多态
- 匿名 trait:支持临时的行为定义
- 组合能力:通过 trait 边界组合多个能力
正确使用 trait 系统可以编写出既灵活又类型安全的代码。