2个版本
0.1.1 | 2024年6月26日 |
---|---|
0.1.0 | 2024年6月26日 |
#297 in 过程宏
25KB
400 代码行
dynex
为动态Rust继承和派生对象不安全特性。
简介
对象安全性是Rust中特质的属性,用于确定特质是否可以作为特质对象使用。然而,许多有用的特质不是对象安全的,例如Clone
和PartialEq
。
例如,你不能简单地写
pub trait Meta: Clone + PartialEq {}
#[derive(Clone, PartialEq)]
pub struct Foo {
meta: Box<dyn Meta>, // The trait `Meta` cannot be made into an object.
}
此crate提供了一个派生对象不安全特质的程序宏
use dynex::*;
#[dyn_trait]
pub trait Meta: Clone + PartialEq {}
#[derive(Clone, PartialEqFix)]
pub struct Foo {
meta: Box<dyn Meta>, // Now it works!
}
注意:PartialEqFix
与PartialEq
有完全相同的行为,但它解决了Rust编译器的一个奇怪行为。对于其他特质,你可以直接派生原始特质名称。
基本示例
以下是如何使用此crate的基本示例
use std::fmt::Debug;
use dynex::*;
#[dyn_trait]
pub trait Meta: Debug + Clone + PartialEq {
fn answer(&self) -> i32 {
42
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct MetaImpl;
impl Meta for MetaImpl {}
#[derive(Debug, Clone, PartialEqFix)]
pub struct Foo {
meta: Box<dyn Meta>,
}
fn main() {
let foo1 = Foo { meta: Box::new(MetaImpl) };
let foo2 = Foo { meta: Box::new(MetaImpl) };
assert_eq!(foo1, foo2);
let foo3 = foo1.clone();
assert_eq!(foo3.meta.answer(), 42);
}
不可派生特质
以Add
特质为例
use std::fmt::Debug;
use std::ops::Add;
use dynex::*;
#[dyn_trait]
pub trait Meta: Debug + Add {}
#[derive(Debug)]
pub struct MetaImpl(String);
impl Meta for MetaImpl {}
impl Add for MetaImpl {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self(self.0 + &rhs.0)
}
}
pub struct Foo {
pub meta: Box<dyn Meta>,
}
impl Add for Foo {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self {
// `Box<dyn Meta>` can be added!
meta: self.meta + rhs.meta,
}
}
}
fn main() {
let foo1 = Foo { meta: Box::new(MetaImpl("114".into())) };
let foo2 = Foo { meta: Box::new(MetaImpl("514".into())) };
let foo3 = foo1 + foo2;
println!("{:?}", foo3.meta); // MetaImpl("114514")
}
致谢
此crate受到以下crate的启发
许可证
MIT.
依赖关系
~250–690KB
~17K SLoC