Как у меня есть поле черты в структуре? - PullRequest
2 голосов
/ 27 апреля 2019

У меня есть код, который я хочу превратить в ящик.Но он включает в себя структуру, которая содержит поле, которое я хочу предоставить пользователю ящика.Но мне нужна функциональность из этого поля, поэтому я хочу указать ее как черту.

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, кажется, уже выяснил более сложные вещи.В последних двух ошибках почти как будто он не осознает, что есть реализация признака для перечисления, потому что он находится в середине определения этой реализации (но он, очевидно, понимает это в других местах).

1 Ответ

2 голосов
/ 27 апреля 2019

С этой чертой что-то немного "выключено":

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

Метод owner не имеет получателя (например, self), поэтому нет необходимости вводить новый параметр типа; Self сделает то же самое.

В order наличие отдельного T не является точно тем же, что и использование Self - это позволяет T и Self быть совершенно разными реализациями RoleTrait. Но это выглядит как довольно странное и необычное требование, тем более что T не появляется в сигнатуре метода.

Ваш код можно исправить, просто следуя более типичному шаблону:

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

Это небольшое изменение приводит к устранению всех ошибок типа и просто оставляет пару небольших ошибок заимствования ( детская площадка ), которые можно довольно легко устранить ( детская площадка ).

...