Реализация метода признаков по умолчанию для всех объектов признаков

У меня есть черта MyTraitи я хочу все черты объектов &MyTrait быть сопоставимыми друг с другом и ни с чем другим. У меня есть это сейчас на основе Как проверить на равенство между чертами объектов?,

Проблема в том, что мне нужно использовать MyTraitComparable везде вместо MyTrait, Есть ли способ обойти это?

use std::any::Any;

trait MyTrait {}

trait MyTraitComparable: MyTrait {
    fn as_any(&self) -> &Any;

    fn equals(&self, other: &MyTraitComparable) -> bool;
}

impl<S: 'static + MyTrait + PartialEq> MyTraitComparable for S {
    fn as_any(&self) -> &Any {
        return self as &Any;
    }

    fn equals(&self, other: &MyTraitComparable) -> bool {
        return match other.as_any().downcast_ref::<S>() {
            None => false,
            Some(a) => self == a,
        };
    }
}

#[derive(PartialEq)]
struct MyObj {
    a: i32,
}
impl MyObj {
    fn new(a: i32) -> MyObj {
        return MyObj { a };
    }
}

impl MyTrait for MyObj {}

fn main() {
    assert!(as_trait_obj_and_compare(&MyObj::new(1), &MyObj::new(1)));
}

fn as_trait_obj_and_compare(obj: &MyTraitComparable, another_obj: &MyTraitComparable) -> bool {
    obj.equals(another_obj)
}

Я пытался переехать as_any а также equals в MyTrait и обеспечение реализации по умолчанию, но

  • Я не думаю, что я могу использовать self в этом случае, так что это не работает.
  • Если я использую trait MyTrait: PartialEq тогда я не могу больше создавать характерные объекты.

1 ответ

Если вы хотите использовать ночной компилятор и нестабильные функции, вы можете использовать специализацию, чтобы избежать двух особенностей:

#![feature(specialization)]

use std::any::Any;

trait MyTrait {
    fn as_any(&self) -> &Any;
    fn equals(&self, other: &MyTrait) -> bool;
}

default impl<S: 'static + PartialEq> MyTrait for S {
    default fn as_any(&self) -> &Any {
        return self as &Any;
    }

    default fn equals(&self, other: &MyTrait) -> bool {
        match other.as_any().downcast_ref::<S>() {
            None => false,
            Some(a) => self == a,
        }
    }
}

#[derive(PartialEq)]
struct MyObj {
    a: i32,
}
impl MyObj {
    fn new(a: i32) -> MyObj {
        return MyObj { a };
    }
}

impl MyTrait for MyObj {}

fn main() {
    assert!(as_trait_obj_and_compare(&MyObj::new(1), &MyObj::new(1)));
}

fn as_trait_obj_and_compare(obj: &MyTrait, another_obj: &MyTrait) -> bool {
    obj.equals(another_obj)
}
Другие вопросы по тегам