我如何在结构中拥有特征字段?
How do I have a trait field in a struct?
我有一些代码想变成一个箱子。但它包含一个结构,其中包含一个我希望由板条箱用户提供的字段。但是我需要那个领域的功能,所以我想将它指定为特征。
pub trait RoleTrait {
fn owner<T: RoleTrait>() -> T;
fn order<T: RoleTrait>(&self) -> usize;
}
pub struct RequestInfo<Role: RoleTrait + PartialEq> {
role: Option<Role>,
name: String,
}
impl<Role: RoleTrait> RequestInfo<Role>
where
Role: std::cmp::PartialEq,
{
fn name(&self) -> String {
self.name.to_string()
}
fn role(&self) -> &Option<Role> {
&self.role
}
fn is_owner(&self) -> bool {
if let Some(role) = self.role {
role == Role::owner()
} else {
false
}
}
fn order(&self) -> usize {
if let Some(role) = self.role {
role.order() + 1
} else {
0
}
}
fn from(name: String) -> RequestInfo<Role> {
RequestInfo::<Role> {
role: None,
name: name,
}
}
fn with_role(name: String, role: Role) -> RequestInfo<Role> {
RequestInfo::<Role> {
role: Some(role),
name: name,
}
}
}
使用 RoleTrait
的两个实现:
#[derive(PartialEq)]
pub enum CourseRole {
Professor,
Marker,
Student,
}
impl RoleTrait for CourseRole {
fn owner<T: RoleTrait>() -> T {
CourseRole::Professor
}
fn order<T: RoleTrait>(&self) -> usize {
if *self == CourseRole::Professor {
0
} else {
1
}
}
}
#[derive(PartialEq)]
pub enum BlogRole {
Owner,
Blogger,
}
impl RoleTrait for BlogRole {
fn owner<T: RoleTrait>() -> T {
BlogRole::Owner
}
fn order<T: RoleTrait>(&self) -> usize {
if *self == BlogRole::Owner {
0
} else {
1
}
}
}
我遇到了 3 个错误。
error[E0282]: type annotations needed
--> src/main.rs:28:18
|
28 | role.order() + 1
| ^^^^^ cannot infer type for `T`
error[E0308]: mismatched types
--> src/main.rs:55:9
|
54 | fn owner<T: RoleTrait>() -> T {
| - expected `T` because of return type
55 | CourseRole::Professor
| ^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found enum `CourseRole`
|
= note: expected type `T`
found type `CourseRole`
error[E0308]: mismatched types
--> src/main.rs:72:9
|
71 | fn owner<T: RoleTrait>() -> T {
| - expected `T` because of return type
72 | BlogRole::Owner
| ^^^^^^^^^^^^^^^ expected type parameter, found enum `BlogRole`
|
= note: expected type `T`
found type `BlogRole`
(另一个枚举重复了第二个错误)
坦率地说,我很惊讶(也很高兴!)我的一些代码是有效的(比如在特征中对 owner
的引用)。当我开始写这个问题时,我有更多的错误,但我无法弄清楚剩下的那些,因为 T
看起来很清楚,而 rustc
似乎已经弄清楚了更难的事情。在最后 2 个错误中,它几乎没有意识到枚举的特征的实现,因为它正在定义该实现(但它显然在其他地方理解)。
有点"off"这种特质:
pub trait RoleTrait {
fn owner<T: RoleTrait>() -> T;
fn order<T: RoleTrait>(&self) -> usize;
}
owner
方法没有receiver(如self
),似乎没有必要引入新的类型参数; Self
会做同样的事情。
在 order
中,有一个单独的 T
并不 完全 与仅使用 Self
相同 - 它允许 T
和 Self
是 RoleTrait
的完全不同的实现。但这感觉像是一个非常奇怪和不寻常的要求,特别是因为 T
没有出现在方法签名中。
您的代码可以通过遵循更典型的模式非常简单地修复:
pub trait RoleTrait {
fn owner() -> Self;
fn order(&self) -> usize;
}
这个小改动导致所有类型错误都得到解决,只留下几个小的借用错误 (playground), which can be quite easily addressed (playground)。
我有一些代码想变成一个箱子。但它包含一个结构,其中包含一个我希望由板条箱用户提供的字段。但是我需要那个领域的功能,所以我想将它指定为特征。
pub trait RoleTrait {
fn owner<T: RoleTrait>() -> T;
fn order<T: RoleTrait>(&self) -> usize;
}
pub struct RequestInfo<Role: RoleTrait + PartialEq> {
role: Option<Role>,
name: String,
}
impl<Role: RoleTrait> RequestInfo<Role>
where
Role: std::cmp::PartialEq,
{
fn name(&self) -> String {
self.name.to_string()
}
fn role(&self) -> &Option<Role> {
&self.role
}
fn is_owner(&self) -> bool {
if let Some(role) = self.role {
role == Role::owner()
} else {
false
}
}
fn order(&self) -> usize {
if let Some(role) = self.role {
role.order() + 1
} else {
0
}
}
fn from(name: String) -> RequestInfo<Role> {
RequestInfo::<Role> {
role: None,
name: name,
}
}
fn with_role(name: String, role: Role) -> RequestInfo<Role> {
RequestInfo::<Role> {
role: Some(role),
name: name,
}
}
}
使用 RoleTrait
的两个实现:
#[derive(PartialEq)]
pub enum CourseRole {
Professor,
Marker,
Student,
}
impl RoleTrait for CourseRole {
fn owner<T: RoleTrait>() -> T {
CourseRole::Professor
}
fn order<T: RoleTrait>(&self) -> usize {
if *self == CourseRole::Professor {
0
} else {
1
}
}
}
#[derive(PartialEq)]
pub enum BlogRole {
Owner,
Blogger,
}
impl RoleTrait for BlogRole {
fn owner<T: RoleTrait>() -> T {
BlogRole::Owner
}
fn order<T: RoleTrait>(&self) -> usize {
if *self == BlogRole::Owner {
0
} else {
1
}
}
}
我遇到了 3 个错误。
error[E0282]: type annotations needed
--> src/main.rs:28:18
|
28 | role.order() + 1
| ^^^^^ cannot infer type for `T`
error[E0308]: mismatched types
--> src/main.rs:55:9
|
54 | fn owner<T: RoleTrait>() -> T {
| - expected `T` because of return type
55 | CourseRole::Professor
| ^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found enum `CourseRole`
|
= note: expected type `T`
found type `CourseRole`
error[E0308]: mismatched types
--> src/main.rs:72:9
|
71 | fn owner<T: RoleTrait>() -> T {
| - expected `T` because of return type
72 | BlogRole::Owner
| ^^^^^^^^^^^^^^^ expected type parameter, found enum `BlogRole`
|
= note: expected type `T`
found type `BlogRole`
(另一个枚举重复了第二个错误)
坦率地说,我很惊讶(也很高兴!)我的一些代码是有效的(比如在特征中对 owner
的引用)。当我开始写这个问题时,我有更多的错误,但我无法弄清楚剩下的那些,因为 T
看起来很清楚,而 rustc
似乎已经弄清楚了更难的事情。在最后 2 个错误中,它几乎没有意识到枚举的特征的实现,因为它正在定义该实现(但它显然在其他地方理解)。
有点"off"这种特质:
pub trait RoleTrait {
fn owner<T: RoleTrait>() -> T;
fn order<T: RoleTrait>(&self) -> usize;
}
owner
方法没有receiver(如self
),似乎没有必要引入新的类型参数; Self
会做同样的事情。
在 order
中,有一个单独的 T
并不 完全 与仅使用 Self
相同 - 它允许 T
和 Self
是 RoleTrait
的完全不同的实现。但这感觉像是一个非常奇怪和不寻常的要求,特别是因为 T
没有出现在方法签名中。
您的代码可以通过遵循更典型的模式非常简单地修复:
pub trait RoleTrait {
fn owner() -> Self;
fn order(&self) -> usize;
}
这个小改动导致所有类型错误都得到解决,只留下几个小的借用错误 (playground), which can be quite easily addressed (playground)。