即使我认为我已经返回了正确的类型数据,但我收到了一个期望的类型参数。

4
我获得了一个期望的类型参数,即使我认为我已经返回了正确的类型数据。我正在学习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() {}

错误信息:
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
1个回答

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

正如您所看到的,方括号中的i32被解析为类型参数。我相信此处局部遮盖了类型i32(具体来说,返回类型是这种通用类型),因此当您返回普通的i32时,编译器会抱怨。虽然这并不重要,因为这不是问题的根源。
问题在于Animal trait要求其get_weight方法在T中是通用的。当您实现trait时,必须提供适用于每种可能类型Tget_weight方法(隐含限制是该类型为Sized)。这应该是不可能的,因为您必须从空气中产生任何给定类型的元素。有些类型甚至没有任何元素!
相反,您有两个选择。首先,您可以制作一个通用trait。其语法为:
trait Animal<T> {
    fn get_weight(&self) -> T;
}

请注意,T是在特征中引入的,而不是在方法中引入的。有了这个设置,你从概念上讲不再拥有一个单一的特征,而是针对每种类型都有一个特征(再次使用隐式的Sized限制)。这意味着给定的类型可以为不同的T值实现该特征。就像你可能会同时为Cat实现Animal<i32>Animal<u32>
如果你仍然希望每种类型只实现一次特征并具有单一的输出类型,则可以使用关联类型。其语法如下:
trait Animal{
    type Weight;

    fn get_weight(&self) -> Self::Weight;
}

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接