【问题标题】:Default trait method implementation for all trait objects所有 trait 对象的默认 trait 方法实现
【发布时间】:2018-03-24 15:02:17
【问题描述】:

我有一个 trait MyTrait,我希望所有的 trait 对象 &MyTrait 都可以相互比较,而不是其他任何东西。我现在有这个基于How to test for equality between trait objects?

问题是我需要在任何地方使用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_anyequals 移动到 MyTrait 并提供默认实现,但是

  • 我认为在这种情况下我不能使用self,所以它不起作用。
  • 如果我使用trait MyTrait: PartialEq,那么我将无法再创建特征对象。

【问题讨论】:

  • 开箱即用,将 MyTrait 重命名为 MyTraitBase 并将 MyTraitComparable 重命名为 MyTrait — 瞧:你在任何地方都在使用 MyTrait
  • @Shepmaster 或许是一种改进,谢谢,但并非无处不在,因为所有结构都必须实现 MyTraitBase

标签: types rust traits default-implementation trait-objects


【解决方案1】:

如果你愿意使用夜间编译器和不稳定的功能,你可以使用specialization 来避免两个特征:

#![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)
}

【讨论】:

  • 虽然我不使用 nightly,但很高兴知道有解决方案正在考虑中!
猜你喜欢
  • 1970-01-01
  • 2021-01-18
  • 2015-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多