如何拥有特质的私密部分?

Fre*_*ios 11 design-patterns traits rust

在我写的箱子里,我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;
}
Run Code Online (Sandbox Code Playgroud)

我希望用户看到和使用forwardstop,但不会do_the_job,而我的数据将只实现do_the_job.

是否有可能设计我的代码来做那样的事情?我试图想象一些解决方案,但没有想到我的想法.

操场


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

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.
    }
}
Run Code Online (Sandbox Code Playgroud)

lhk*_*lhk 6

特性类似于接口

特性是Rust唯一的接口概念。

接口旨在记录可用方法,而具有私有方法的接口则毫无意义。相应地,在Rust中,您不能在一个特征上拥有不同级别的可见性。如果可以看到特征,则始终可以看到所有特征。但是,Rust特征与接口有细微的不同:它们结合了声明和实现。我看到具有一些私有功能的特征将是多么直观。

一段时间以来,可以将特征分为公共部分和私有部分。您将具有两个特征,一个特征包含您的公共接口,另一个特征具有您的私有功能,但是在较新版本的Rust中已将其删除

当前的解决方法仍然是分割特征,但是私有部分现在必须由私有模块中的公共特征来表示。为了说明这一点,下面是一些示例代码:

// 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);
}
Run Code Online (Sandbox Code Playgroud)

  • 我已经阅读了一些,似乎使依赖于私有特征的公共特征将来不会成为错误。有关新建议的规则,请参见[RFC 2145](https://github.com/rust-lang/rfcs/blob/master/text/2145-type-privacy.md)。 (3认同)