Реализация метода признаков по умолчанию для всех объектов признаков
У меня есть черта 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)
}