我可以在Rust中使用泛型函数参数来创建新变量吗?

时间:2016-05-19 22:23:51

标签: generics rust

是否可以在Rust中创建泛型参数类型的实例?

我来自C ++背景,使用模板类型在实际的函数体中创建类型是完全有效的。

我试图在此函数中创建类型为T的变量,但我不确定如何。

我只是希望能够创建T类型的对象,加载它,然后将其插入HashMap

fn load<T>(&mut self, id: String, path: String)
    where T: AssetTrait + 'static
{
    // let asset : T = T; this doesn't work?

    asset.load(path);

    // self.assets.insert(id, Box::new<T>(asset));
}

这是我的所有代码:

trait AssetTrait {
    fn load(&self, path: String) {
        // Do nothing
        // Implement this in child asset object
    }
}

struct AssetManager {
    assets: HashMap<String, Box<AssetTrait + 'static>>,
}

impl AssetManager {
    fn new() -> AssetManager {
        let asset_manager = AssetManager { assets: HashMap::new() };

        return asset_manager;
    }

    fn load<T>(&mut self, id: String, path: String)
        where T: AssetTrait + 'static
    {
        // let asset : T = T; this doesn't work?

        asset.load(path);

        // self.assets.insert(id, Box::new<T>(asset));
    }
}

1 个答案:

答案 0 :(得分:4)

在C ++中声明类似T asset;的变量时,假设T有一个默认构造函数(鸭子类型的编译时版本)。使用没有默认构造函数的类型实例化T是一个编译器错误,但如果没有这样的实例化,它就没问题。

在Rust中你不能&#34;假设&#34;类型参数支持操作。您必须在类型参数上使用边界指定支持的操作。

那就是说,你必须选择:

AssetTrait

中定义您自己的构造函数,例如关联函数

例如,您可以将load声明为不带self参数并返回Self的关联函数,并调用T::load(path)来实例化T }:

use std::collections::HashMap;

trait AssetTrait {
    fn load(path: String) -> Self;
}

struct AssetManager {
    assets: HashMap<String, Box<AssetTrait + 'static>>,
}

impl AssetManager {
    fn new() -> AssetManager {
        let asset_manager = AssetManager { assets: HashMap::new() };
        return asset_manager;
    }

    fn load<T>(&mut self, id: String, path: String)
        where T: AssetTrait + 'static
    {
        let asset = T::load(path);
        self.assets.insert(id, Box::new(asset));
    }
}

使用具有关联函数

等构造函数的预定义特征

在Rust中,Default特征用于此目的:

use std::collections::HashMap;

trait AssetTrait {
    fn load(&mut self, path: String);
}

struct AssetManager {
    assets: HashMap<String, Box<AssetTrait + 'static>>,
}

impl AssetManager {
    fn new() -> AssetManager {
        let asset_manager = AssetManager { assets: HashMap::new() };
        return asset_manager;
    }

    fn load<T>(&mut self, id: String, path: String)
        where T: Default + AssetTrait + 'static
    {
        let mut asset = T::default();
        asset.load(path);
        self.assets.insert(id, Box::new(asset));
    }
}