即使我认为已经返回了正确的类型数据,我也得到了预期的类型参数。我正处于锈蚀通用材料的学习阶段。
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
答案 0 :(得分: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
特性要求其get_weight
方法在T
中是通用的。在实现特征时,必须提供一个get_weight
方法,该方法适用于每种可能的类型T
(类型为Sized
的隐式限制) 。这应该是不可能的,因为您必须凭空产生任何给定类型的元素。有些类型甚至没有任何元素!
相反,您有两种选择。首先,您可以创建一个通用特征。语法是
trait Animal<T> {
fn get_weight(&self) -> T;
}
请注意,T
是用特征而不是方法引入的。使用此设置,从概念上讲,您不再具有单个特征,而是每个类型都具有一个特征(同样具有隐式Sized
界限)。这意味着给定的类型可以为T
的不同值实现特征。就像您可能同时为Animal<i32>
实现了Animal<u32>
和Cat
。
如果仍然希望每个类型仅实现一次特征并具有单个输出类型,则可以使用关联的类型。语法是
trait Animal{
type Weight;
fn get_weight(&self) -> Self::Weight;
}
现在,当在类型上实现此特征时,必须提供输出类型。您可以通过在trait实现中添加行Cat
来实现type Weight = i32;
。然后,get_weight
方法只需要返回i32
,就像您已经拥有的一样。