如何在Rust中通过传入类型创建实现指定Trait的新对象
问题:如何从实现Trait的类型创建对象(无需已有实例)
我需要实现一个函数,能够从任何实现了某Trait的struct创建新对象,但我的程序中没有这类对象的实例——它们由库的使用者实现。当前的create_obj函数需要接收实现该Trait的struct对象,但我希望直接传入类型而非实例。
原代码
trait Tr { fn new() -> Self; } struct St {} impl Tr for St { fn new() -> Self { Self } } // 我希望这个函数能为我创建任何实现Tr的对象 fn create_obj<T: Tr>(t: T) -> Box<dyn Tr> { Box::new(T::new()) } #[cfg(test)] mod tests { use crate::{create_obj, St}; #[test] fn it_works() { // 我想传入实现Trait的struct类型,而非struct对象 create_obj(St); } }
错误提示
^^ help: use struct literal syntax instead: `St {}`
解决方案
方法1:移除不必要的参数,使用涡轮鱼语法指定类型
你的create_obj函数其实不需要接收T的实例,因为T: Tr约束已经保证了T实现了new方法。直接移除参数,调用时用**涡轮鱼语法(::<>)**指定类型即可:
trait Tr { fn new() -> Self; } struct St {} impl Tr for St { fn new() -> Self { Self } } // 修改后的函数:无需传入实例 fn create_obj<T: Tr>() -> Box<dyn Tr> { Box::new(T::new()) } #[cfg(test)] mod tests { use crate::{create_obj, St}; #[test] fn it_works() { // 用涡轮鱼语法指定要创建的类型 let obj = create_obj::<St>(); } }
方法2:使用PhantomData作为类型标记(可选)
如果你希望通过参数传递类型信息(而非涡轮鱼语法),可以用std::marker::PhantomData作为类型占位符,它不会占用内存:
use std::marker::PhantomData; trait Tr { fn new() -> Self; } struct St {} impl Tr for St { fn new() -> Self { Self } } // 接收PhantomData作为类型标记 fn create_obj<T: Tr>(_: PhantomData<T>) -> Box<dyn Tr> { Box::new(T::new()) } #[cfg(test)] mod tests { use crate::{create_obj, St}; use std::marker::PhantomData; #[test] fn it_works() { // 传入PhantomData来指定类型 let obj = create_obj(PhantomData::<St>); } }
内容的提问来源于stack exchange,提问作者Lev Rubel
相关产品推荐
相关产品推荐

