首页 > 解决方案 > 我得到了一个预期的类型参数,即使我认为我已经返回了正确的类型数据

问题描述

我得到了一个预期的类型参数,即使我认为我已经返回了正确的类型数据。我正处于 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

标签: typesrusttraits

解决方案


查看此处的编译器警告非常有帮助。

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(具体来说,返回类型是这种泛型类型),所以当你返回一个 normali32时,编译器会抱怨。这并不重要,因为这不是问题的根源。

这里的问题是Animaltrait 要求它的get_weight方法在T. 当你实现 trait 时,你必须提供一个get_weight适用于所有可能类型的方法T(隐含限制类型是Sized)。这应该是不可能的,因为您必须凭空产生任何给定类型的元素。有些类型甚至没有任何元素!

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

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

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

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

trait Animal{
    type Weight;

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

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


推荐阅读