即使我认为我已经返回了正确的类型数据,我也得到了预期的类型参数。我处于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)
在这里查看编译器警告非常有帮助。
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
,就像您已经拥有的一样。