You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 23:24:46