当Trait非对象安全时,替代dyn的可扩展解决方案有哪些?
需求与问题
我想要开发一个通过命令行参数选择所用结构体的Rust程序,示例代码如下:
trait Animal { fn sound(&self) -> &str; } struct Dog {} impl Animal for Dog { fn sound(&self) -> &str { "Woof!" } } struct Cat {} impl Animal for Cat { fn sound(&self) -> &str { "Miau!" } } trait Place { fn name(&self) -> &str; } struct Museum {} impl Place for Museum { fn name(&self) -> &str { "museum" } } struct Hotel{} impl Place for Hotel { fn name(&self) -> &str { "hotel" } } fn get_animal(animal: &str) -> Box<dyn Animal> { match animal { "dog" => Box::new(Dog{}), "cat" => Box::new(Cat{}), _ => todo!() } } fn get_place(place: &str) -> Box<dyn Place> { match place { "museum" => Box::new(Museum{}), "hotel" => Box::new(Hotel{}), _ => todo!() } } fn sentence(animal: Box<dyn Animal>, place: Box<dyn Place>) { println!("{} We are at {}.", animal.sound(), place.name()); } fn main() { let args: Vec<String> = env::args().collect(); let animal = get_animal(&args[1]); let place = get_place(&args[2]); sentence(animal, place); }
但实际使用的Trait不具备对象安全性,无法使用dyn。目前我只能为所有结构体组合编写match分支:
match (animal, place) { ("dog", "museum") => sentence(Dog{}, Museum{}), ("dog", "hotel") => sentence(Dog{}, Hotel{}), ("cat", "museum") => sentence(Cat{}, Museum{}), ("cat", "hotel") => sentence(Cat{}, Hotel{}), }
后续我会添加更多结构体,这种方式完全不具备可扩展性。我想知道是否存在可扩展的解决方案?能否通过宏自动生成match分支,或是有更优的方案?
我使用的Trait包括:
- PrimeField
- ConstraintSynthesizer
- PolynomialCommitment
修改这些Trait使其具备对象安全性并非良策,原因如下:
- 这些库实现了复杂的数学算法,难以理解;
- 该程序用于基准测试库性能,修改Trait可能影响性能。
内容的提问来源于stack exchange,提问作者Prankster2k
相关产品推荐
相关产品推荐

