2015-09-27 47 views
0

我在理解如何使用特征和所有权方面遇到了一些麻烦。下面的示例工作:无法通过引用实现特征的类型调用函数

struct X([u8; 4]); 

impl X { 
    pub fn get(&self, n: usize) -> u8 { 
     self.0[n] 
    } 
} 

fn f1(x: &X) { 
    println!("{}", x.get(1)); 
    f2(&x); 
} 

fn f2(x: &X) { 
    println!("{}", x.get(2));  
} 

fn main() { 
    let z1 = X([1u8, 2u8, 3u8, 4u8]); 
    f1(&z1); 
} 

但是当我尝试创建一个特质(这里XT)与get

trait XT { 
    fn get(&self, n: usize) -> u8; 
} 

struct X([u8; 4]); 

impl XT for X { 
    fn get(&self, n: usize) -> u8 { 
     self.0[n] 
    } 
} 

fn f1<T: XT>(x: &T) { 
    println!("{}", x.get(1)); 
    f2(&x); 
} 

fn f2<T: XT>(x: &T) { 
    println!("{}", x.get(2));  
} 

fn main() { 
    let z1 = X([1u8, 2u8, 3u8, 4u8]); 
    f1(&z1); 
} 

失败,出现以下错误消息编译:

的性状XT未实施类型&T

如果我将f2(&x)更改为f2(x),它可以正常工作。我的期望是用特性来取代类型,一切都会奏效。

回答

3

问题是,您正试图通过&&Tf2。这意味着它期望&T实施XT,那就是而不是你说什么:你说T实施XT

可以修改f1正确表达通过使用where T: XT, for<'a> &'a T: XT子句此约束,但你不能从main调用f1因为&X没有实现XT。所以你去添加的实现,以及然后该代码的工作原理......但说实话,只是删除该&并调用f2(x)来代替。

换一种方式:仅仅因为一个类型实现的性状意味着指向该类型落实特质。

+0

但令人困惑的是,它在第​​一种情况下工作正常。 (免责声明:我没有全面的Rust视图,所以我可能完全错误)这看起来像一个非常常见的场景:你编写一些采用特定类型的函数,然后你意识到你可以使用它来获得更多的东西。因此,您可以创建一个Trait并用函数定义中的特征类型替换(使用某种语法)。使它工作的语法不是很符合人体工程学。 – Hernan

+1

@Hernan它在第一种情况下起作用,因为'z1'的类型是'X',因此'&z1'是'&X'类型。当你调用'f1'时,编译器推断'&T =&X'因此'T = X'。当用'&x'调用'f2'时,它会得到'&T = && X',因此'T =&X','&X'不执行'XT'。 –

+0

感谢您的解释。我现在明白了。我认为将特征语法等同于类型的语法会更符合人体工程学,但我想我错过了关于该语言的重要事情。 – Hernan

相关问题