Rust의 스타일 특성 있음

11098 단어 rust
나는 최근에 Rust trait instances on bounded generic types을 실험했습니다. 이것은 impl<T: SomeTrait> AnotherTrait for T , 즉 AnotherTrait 인스턴스의 존재로 인해 생성된 SomeTrait 인스턴스의 멋진 표현입니다.

다음은 비슷하지만 약간 더 복잡한 예입니다.

나는 모두 공통된 기본 속성 집합을 가진 여러 가지를 가지고 있습니다. 나는 공통 기본 집합이 하나의 특성으로 설명되고 사물이 다른 모든 방식이 공통적인 것에 의존할 수 있는 다른 특성으로 설명되기를 바랍니다.

/// First, a simple base struct:
///
/// It contains things that are common to a set of structs.
#[derive(Debug, Clone)]
struct Base {
    foo: u64,
    bar: u64,
}

impl Base {
    fn new(foo: u64, bar: u64) -> Self {
        Self { foo, bar }
    }
}

/// Then, a trait that describes it
///
/// This is an abstract interface over the same struct. It allows us to
/// access other structs as if they were `Base`, as long as they have
/// some way to access a `Base`, e.g. by having a field of type `Base`.
trait BaseTrait {
    fn foo(&self) -> u64;
    fn bar(&self) -> u64;
}

/// Next, a trait that describes things that contain `Base`s
trait HasBase {
    fn get_base(&self) -> Base;
}

/// ...of which the simplest one is that `Base` has itself;
/// but to avoid infinite recursion, we `impl BaseTrait` for
/// `Base`.
impl BaseTrait for Base {
    fn foo(&self) -> u64 {
        self.foo
    }

    fn bar(&self) -> u64 {
        self.bar
    }
}

/// This is the crux:
///
/// A recursive trait instance that enables `BaseTrait`
/// calls on any thing that `HasBase` (i.e. has a `Base`).
impl<T: HasBase> BaseTrait for T {
    fn foo(&self) -> u64 {
        self.get_base().foo()
    }

    fn bar(&self) -> u64 {
        self.get_base().bar()
    }
}

/// Now, a `Thing` with a `Base`
#[derive(Debug, Clone)]
struct Thing {
    base: Base,
    baz: u64,
}

impl Thing {
    pub fn new(base: Base, baz: u64) -> Self {
        Thing { base, baz }
    }
}

/// If `BaseTrait` had many functions, we'd save a lot of lines here.
///
/// This `impl HasBase for Thing` implies `impl BaseTrait for Thing`.
impl HasBase for Thing {
    fn get_base(&self) -> Base {
        self.base.clone()
    }
}

/// So far, this is all great!
///
/// Now I want to make another trait that depends on BaseTrait
trait ExtensionTrait: BaseTrait {
    fn foo_bar_sum(&self) -> u64 {
        self.foo() + self.bar()
    }

    fn bar_baz_sum(&self) -> u64 {
        self.bar() + self.baz()
    }

    fn baz(&self) -> u64;
}

/// And what's more natural than give this trait to `Thing`
impl ExtensionTrait for Thing {
    fn baz(&self) -> u64 {
        self.baz
    }
}

fn main() {
    let some_thing = Thing::new(Base::new(2, 3), 5);

    println!(
        "foo = {}, bar = {}, baz = {}",
        some_thing.foo(),
        some_thing.bar(),
        some_thing.baz(),
    );

    println!(
        "foo + bar = {}, bar + baz = {}",
        some_thing.foo_bar_sum(),
        some_thing.bar_baz_sum()
    );
}

좋은 웹페이지 즐겨찾기