我尝试使用trait变量而不将其装箱。
像下面这样,创建trait实现的struct示例而不装箱是很清楚的,但是我不能将这个trait实现的示例设置为其他struct的字段。
我知道使用泛型可以解决这个问题,(比如struct UserCertification\<T\> { current_work: T }
)
但我不想用它。
有没有其他方法可以使用trait实现的示例而不将其装箱?
#[derive(Copy, Clone)]
enum Job { Teacher, Police }
trait Namable {
fn name(&self) -> &'static str;
}
// Sample trait-implemented struct 1
struct TemporaryTeacher { }
impl Namable for TemporaryTeacher {
fn name(&self) -> &'static str { "T.Teacher" }
}
// Sample trait-implemented struct 2
struct GeneralTeacher { }
impl Namable for GeneralTeacher {
fn name(&self) -> &'static str { "G.Teacher" }
}
// Returns the instance wihtout Box.
fn create_named_object(job: Job, name: &str) -> impl Namable {
TemporaryTeacher() // one of the result that implements trait Namable.
}
struct UserCertification {
name: String,
current_work: dyn Namable, // <- ERROR: cannot use dynamic directly. use Box<dyn Namable>.
}
fn main() {
let named_object = create_named_object(Job::Teacher, "");
let user = UserCertification("John", named_object);
}
我试图找出如何创建示例没有装箱过程。为了解决这个问题,我搜索并发现使用泛型可以处理这个问题,但它不是一个理想的解决方案。
1条答案
按热度按时间oyxsuwqo1#
只有三种方法可以在Rust中完成您正在尝试的工作。每种方式都有自己的权衡,所以哪种更好将取决于您的用例。
使用泛型
这可能是最简单的方法,也是最有效的内存使用和性能。主要的缺点是,你不能在同一代码中混合使用多种类型,也不能动态地更改存储在变量中的类型:
Playground
使用trait对象
trait对象写为
dyn Namable
,并且它 * 必须 * 在某种引用后面,例如。&dyn Namable
、Box<dyn Namable>
、Rc<dyn Namable>
或Arc<dyn Namable>
。Playground
这相当容易使用,允许非常广泛的用途,包括混合不同的类型和动态更改,但它也是三种解决方案中最慢的。这也是大多数高级语言做事情的方式(例如Java、Python等)。但是some traits cannot be made into trait objects。
使用枚举
Playground
这种解决方案允许混合不同的类型并动态更改,它通常比现代CPU上的trait对象解决方案更快。但是:
enum_dispatch
这样的板条箱可能会有所帮助)。