我得到了预期的类型参数,即使我认为我已经返回了正确的类型数据

Lao*_*tih 3 types traits rust

即使我认为我已经返回了正确的类型数据,我也得到了预期的类型参数。我处于rust通用材料的学习阶段。

struct Cat {
    weight: i32,
}

trait Animal{
    fn get_weight<T>(&self) -> T;
}

impl Animal for Cat {
    fn get_weight<i32>(&self) -> i32 {
        self.weight // I got error in here
    }
}

fn main() {}
Run Code Online (Sandbox Code Playgroud)

错误信息:

mismatched types

expected type parameter, found i32

note: expected type `i32` (type parameter)
         found type `i32` (i32)

expected `i32` because of return type
expected type parameter, found i32
Run Code Online (Sandbox Code Playgroud)

SCa*_*lla 6

在这里查看编译器警告非常有帮助。

warning: type parameter `i32` should have an upper camel case name
  --> src/main.rs:10:19
   |
10 |     fn get_weight<i32>(&self) -> i32 {
   |                   ^^^ help: convert the identifier to upper camel case: `I32`
   |
   = note: #[warn(non_camel_case_types)] on by default
Run Code Online (Sandbox Code Playgroud)

如您所见,i32括号之间的被解析为类型参数。我相信这会局部遮盖类型i32(特别是返回类型就是这种泛型类型),因此当您返回normal时i32,编译器会抱怨。这并不是真正相关的,因为这不是问题的根源。

这里的问题是该Animal特性要求其get_weight方法在中是通用的T。实现特征时,必须提供一种get_weight适用于每种可能类型的方法T(该类型为的隐式限制Sized)。这应该是不可能的,因为您必须凭空产生任何给定类型的元素。有些类型甚至没有任何元素!

相反,您有两种选择。首先,您可以创建一个通用特征。语法是

trait Animal<T> {
    fn get_weight(&self) -> T;
}
Run Code Online (Sandbox Code Playgroud)

请注意,它T是用特征而不是方法引入的。使用此设置,从概念上讲,您不再具有单个特征,而是每个类型都具有一个特征(同样具有隐式Sized边界)。这意味着给定类型可以为的不同值实现特征T。就像您可能同时针对Animal<i32>Animal<u32>实现Cat

如果仍然希望每种类型仅实现一次特征并具有单个输出类型,则可以使用关联的类型。语法是

trait Animal{
    type Weight;

    fn get_weight(&self) -> Self::Weight;
}
Run Code Online (Sandbox Code Playgroud)

现在,当您在类型上实现此特征时,必须提供输出类型。您可以Cat通过type Weight = i32;在trait实现中添加该行来实现。然后,该get_weight方法只需要返回即可i32,就像您已经拥有的一样。