Struct 有没有一种基于trait实现创建结构的方法?

Struct 有没有一种基于trait实现创建结构的方法?,struct,rust,traits,implementation,Struct,Rust,Traits,Implementation,我尝试将结构与一个方法的多个实现结合使用: trait{fn apply(&self)->vec;} 结构条{vec:vec} 注入棒{ pub fn new(vec:vec)->Self{Self{vec} 发布fn测试(和自测试){ //这里的东西 println!((“方法:{:?}”,self.apply()); //那里的东西 } } 棒材的impl特性{ fn apply(&self)->Vec{self.Vec.iter().map(|x | x.pow(2)).collect()

我尝试将结构与一个方法的多个实现结合使用:

trait{fn apply(&self)->vec;}
结构条{vec:vec}
注入棒{
pub fn new(vec:vec)->Self{Self{vec}
发布fn测试(和自测试){
//这里的东西
println!((“方法:{:?}”,self.apply());
//那里的东西
}
}
棒材的impl特性{
fn apply(&self)->Vec{self.Vec.iter().map(|x | x.pow(2)).collect()}
}
棒材的impl特性{
fn apply(&self)->Vec{self.Vec.iter().map(|x | x+2).collect()}
}
fn main(){
新的(vec![1,2,3]).test();
新的(vec![1,2,3]).test();
}
这将返回:

>[1,4,9];
>>> [3,4,5];
我知道我可以创建两个不同的结构来实现这些方法,但这感觉是错误的,因为它可能有很多冗余代码。 我还知道我可以参考该实施方法:

trait{fn apply(vec:&vec)->vec;}
impl结构{
//fn新
测试(&self,t:&impl-Trait){
//这里的东西
println!(“{:?}”,t::apply(&self.vec));
//那里的东西
}
}
这样构造;
这样构造;
这种方式的impl特征{fn apply(vec:&vec)->vec{/};
这种方式的impl Trait{fn apply(vec:&vec)->vec{/};
fn main(){
让这条路=这条路{};
让那条路=那条路{};
让问题=Bar::new(vec![1,2,3]);
问题。测试(以这种方式);
问题。测试(以那种方式);
}
当我想在给定结构中使用许多参数时,这种方法似乎不必要地复杂:

fn爬山者(&self,nullary,op:&impl nullary运算符,一元数,op:&impl一元运算符,…){
self.vec=nullary_op();
self.vec=一元运算(&self.vec,self.n,self.m,self.jobs,self.stuff,…);
}

这似乎是一种被诅咒的编写代码的方式。如果方法实现不使用参数,例如
m
,而其他使用特性来定义共享行为,会发生什么情况。在您的示例中,您希望以不同的方式实现相同的特性。这与一个特征的目的背道而驰。与您尝试使用的两个结构不同,您应该具有两个特点:

trait ThisWay{
fn apply(&self)->Vec;
}
那样的特点{
fn apply(&self)->Vec;
}
现在,您可以为结构实现这两个特性:

结构栏{
维克:维克,
}
这条路对吧{
fn应用(&self)->Vec{
self.vec.iter().map(|x | x.pow(2)).collect()
}
}
酒吧就这样吧{
fn应用(&self)->Vec{
self.vec.iter().map(|x | x+2).collect()
}
}
由于
Bar
实现了
ThisWay
ThatWay
,因此它现在有了
apply
方法的两个定义。为了消除它们之间的歧义,我们必须使用完全限定语法:

让这个_bar=bar::new(vec![1,2,3]);
普林顿!((“方法:{:?},::应用(&this_-bar));
让那个_bar=bar::new(vec![1,2,3]);
普林顿!(“方法:{:?},::应用(&that_-bar));
正如预期的那样,您会得到两种不同的输出:

方法:[1,4,9]
方法:[3,4,5]

作为另一个答案的替代,您还可以使用与原始示例更相似的方法,使用泛型和零大小的结构类型作为您要使用的方法的“标记”。下面是一个完整的示例:

// PhantomData allows us to "use" a generic without having an actual field
use std::marker::PhantomData;

// These structs will be used to indicate which implementation we want
struct ThisWay;
struct ThatWay;

trait Trait { fn apply(&self) -> Vec<usize>; }

struct Bar<X> {
    vec: Vec<usize>,
    // This extra field is here to stop the compiler complaining about not using X
    _marker: PhantomData<X>,
}

impl<X> Bar<X> {
    pub fn new(vec: Vec<usize>) -> Self { Self { vec, _marker: PhantomData } }

    // Note the new "where" clause here - we can only implement this function if Bar<X> implements Trait
    pub fn test(&self) where Self: Trait {
        // Things here
        println!("Method: {:?}", self.apply()); 
        // Things there
    }
}

impl Trait for Bar<ThisWay> {
    fn apply(&self) -> Vec<usize> { self.vec.iter().map(|x| x.pow(2)).collect() }
}

impl Trait for Bar<ThatWay> {
    fn apply(&self) -> Vec<usize> { self.vec.iter().map(|x| x + 2).collect() }
}

fn main() {
   Bar::<ThisWay>::new(vec![1,2,3]).test();
   Bar::<ThatWay>::new(vec![1,2,3]).test();
}
这种方法与另一个答案的语义不同:另一个答案允许您构造一个能够与两个函数一起使用的
,而这种方法将您锁定在类型级别的一个实现中,因为
Bar
Bar
是两种独立的类型,每种类型仅提供一个
apply
功能。在某些情况下,这可能是类型安全所需要的,但可能不是此特定情况所需要的

// since x is declared as `Bar<ThatWay>`, we can only ever use the `ThatWay` implementation of `apply`/`test`
let x: Bar<ThatWay> = Bar::new(vec![1, 2, 3]);
x.test(); // -> Method: [3, 4, 5]
//由于x被声明为'Bar',我们只能使用'apply`/'测试的'ThatWay'实现`
设x:Bar=Bar::new(vec![1,2,3]);
x、 test();//->方法:[3,4,5]

我知道我的问题有一个简单的解决方案,谢谢你,你是我的救星:D@DanielZdancewicz没问题除了
之外,您还想为其他任何东西实现
特征
?如果没有,只需为
X
实现它,并使
apply()
使用
&Bar
而不是
&self
。谢谢,我也想知道如何使用PhantomData,干杯
// since x is declared as `Bar<ThatWay>`, we can only ever use the `ThatWay` implementation of `apply`/`test`
let x: Bar<ThatWay> = Bar::new(vec![1, 2, 3]);
x.test(); // -> Method: [3, 4, 5]