design-patterns - 如何拥有特质的私有(private)部分?

标签 design-patterns rust traits

在我编写的 crate 中,我有一堆内部 struct 对用户公开并且共享一些代码。一些共享代码是公开的,一些是内部实现。为了有效地共享代码,我使用了宏,但是现在项目有更多的功能,这开始变得困惑,我对这种语义不满意。

我想使用一个特征,但不公开实现。例如:

pub trait MyTrait {
    type Next;

    // This function is for the user.
    fn forward(&self) -> Self::Next {
        self.do_the_job()
    }

    // This function is for the user.
    fn stop(&self) {
        self.do_the_job();
    }

    // This function is an implementation detail.
    fn do_the_job(&self) -> Self::Next;
}

我希望用户看到并使用forwardstop,而不是do_the_job,而我的数据只会实现do_the_job

是否可以设计我的代码来执行类似的操作?我曾尝试想出一些解决方案,但什么也没有想到。

Playground


在具有继承性的面向对象语言中,我会这样做(伪代码):

public interface MyTrait {
    type Next;

    fn forward(&self) -> Self::Next;

    fn stop(&self);
}

public abstract class MyCommonCode extends MyTrait {
    fn forward(&self) -> Self::Next {
        self.do_the_job()
    }

    fn stop(&self) {
        self.do_the_job();
    }

    protected abstract fn do_the_job(&self) -> Self::Next;
}

public MyType extends MyCommonCode {
    type Next = i32;

    protected override fn do_the_job(&self) -> Self::Next {
        // etc.
    }
}

最佳答案

性状类似于 interfaces :

Traits are Rust’s sole notion of interface.

接口(interface)是用来记录可用方法的,拥有私有(private)方法的接口(interface)是没有意义的。相应地,在 Rust 中,你不能在一个特征中有不同级别的可见性。如果你能看到特质,你总能看到它的全部。然而,Rust traits 与接口(interface)有微妙的不同:它们结合了声明和实现。我看到了具有一些私有(private)函数的特征是多么直观。

一段时间以来,可以将特征分为公共(public)部分和私有(private)部分。你会有两个特征,一个包含你的公共(public)接口(interface),另一个包含你的私有(private)功能,但这是 being removed in newer versions of Rust .

当前的解决方法仍然是拆分特征,但私有(private)部分现在必须由私有(private)模块中的公共(public)特征表示。为了解释这一点,这里有一些示例代码:

// this module contains a public trait Inc, to increment a value
// and it implements it by using a private trait Add
mod my_math {
    pub struct Val {
        pub val: i32,
    }

    // this is necessary to encapsulate the private trait
    // the module is private, so the trait is not exported
    mod private_parts {
        pub trait Add {
            fn add(&mut self, i32);
        }
    }

    // in the following code, we have to use adequate namespacing
    impl private_parts::Add for Val {
        fn add(&mut self, other: i32) {
            self.val += other;
        }
    }

    pub trait Inc: private_parts::Add {
        fn inc(&mut self);
    }

    impl Inc for Val {
        fn inc(&mut self) {
            use my_math::private_parts::Add;
            self.add(1)
        }
    }
}

fn main() {
    use my_math::Inc;
    let mut b = my_math::Val { val: 3 };
    println!("value: {}", b.val);
    b.inc();
    println!("value: {}", b.val);
}

关于design-patterns - 如何拥有特质的私有(private)部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53204327/

相关文章:

reference - 我什么时候不应该为引用该特征的实现者而实现该特征?

design-patterns - 设计模式——抽象工厂模式和开闭原则

design-patterns - 何时在类名中包含设计模式名称?

rust - 如何在编译过程中注释代码以生成工件?

c++ - 替换失败不是枚举的错误 (SFINAE)

c++ - 有没有更好的方法来检查 STL 容器是否是多*容器

javascript - three.js继承模式

java - 通用父对象不能在没有转换的情况下作为子对象返回

使用特征对象时,使用rust 具有特征绑定(bind)的泛型类型

rust - 如何实现 `From<some trait' s 关联类型>?`