我如何在结构中有一个特征字段?

问题描述 投票:2回答:1

我有一些代码,我想变成一个箱子。但它包含一个结构,其中包含我希望由包的用户提供的字段。但是我需要来自该领域的功能,所以我想将其指定为特征。

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个错误中,它几乎就像没有意识到枚举的特征的实现,因为它正在定义实现的中间(但它显然在其他地方理解)。

enums rust traits
1个回答
2
投票

这个特性让人觉得有些“偏离”:

pub trait RoleTrait {
    fn owner<T: RoleTrait>() -> T;
    fn order<T: RoleTrait>(&self) -> usize;
}

owner方法没有接收器(例如self),因此似乎没有必要引入新的类型参数; Self将做同样的事情。

order,有一个单独的T与使用Self不完全相同 - 它允许TSelfRoleTrait完全不同的实现。但这感觉就像一个非常奇怪和不寻常的要求,特别是因为T没有出现在方法签名中。

通过遵循更典型的模式,可以非常简单地修复代码:

pub trait RoleTrait {
    fn owner() -> Self;
    fn order(&self) -> usize;
}

这个小小的改变导致所有类型错误得到解决,只留下几个小借用错误(playground),这很容易解决(playground)。

© www.soinside.com 2019 - 2024. All rights reserved.