代码之家  ›  专栏  ›  技术社区  ›  Boiethios

如何拥有个性的一部分?

  •  9
  • Boiethios  · 技术社区  · 7 年前

    在我写的箱子里,我有一堆 struct 它对用户是公共的,并且共享一些代码。有些共享代码是公共的,有些是内部实现。为了有效地共享代码,我正在使用宏,但是现在项目有了更多的特性,这就开始变得混乱,我对它的语义不满意。

    我想使用trait,但不公开实现。例如:

    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;
    }
    

    我希望用户看到并使用 forward 和 stop ,但不是 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.
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  9
  •   Shepmaster Tim Diekmann    7 年前

    特征与 interfaces :

    接口是用来记录可用方法的,拥有一个带有私有方法的接口是没有意义的。相应地,在锈菌中,一个性状不能有不同程度的可见性。如果你能看到这种特质,你总能看到它的全部。然而,Rust特性与接口有细微的不同:它们结合了声明和实现。我明白了拥有一些私人功能的特质是多么的直观。

    有一段时间,把一种特质分成公共和私人两部分是可能的。你会有两个特点,一个包含你的公共接口,另一个包含你的私有功能,但这是 being removed in newer versions of Rust

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

    // 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);
    }
    
    推荐文章