2017-07-25 2 views
2

Y a-t-il un meilleur moyen que de simplement tout mettre dans le même module?Est-il possible d'avoir un module qui est partiellement accessible à l'extérieur d'une caisse et partiellement seulement à l'intérieur de la caisse?

sub_module.rs

pub struct GiantStruct { /* */ } 

impl GiantStruct { 

    // this method needs to be called from outside of the crate. 
    pub fn do_stuff(/* */) { /* */ }; 
} 

lib.rs

pub mod sub_module; 
use sub_module::GiantStruct; 

pub struct GiantStructBuilder{ /* */ } 

impl GiantStructBuilder{ 
    pub fn new_giant_struct(&mut self) -> GiantStruct { 
     // Do stuff depending on the fields of the current 
     // GiantStructBuilder 
    } 
} 

Le problème est avec GiantStructBuilder::new_giant_struct(); cette méthode devrait créer un nouveau GiantStruct mais pour ce faire vous avez besoin soit pub fn new() -> GiantStruct à l'intérieur de sub_module.rs ou tous les champs de GiantStruct doivent être publiques. Les deux options permettent d'accéder depuis l'extérieur de ma caisse.

Tout en écrivant cette question, je réalisais que je pouvais faire quelque chose comme ceci:

sub_module.rs

pub struct GiantStruct { /* */ } 

impl GiantStruct { 
    // now you can't call this method without an appropriate 
    // GiantStructBuilder 
    pub fn new(&mut GiantStructBuilder) -> GiantStruct { /* */ }; 

    pub fn do_stuff(/* */) { /* */ }; 
} 

Cependant, cela semble contre-intuitif vraiment que normalement l'appelant est la chose qui est agissant alors que les variables de fonction sont ce qui est agi sur, ce qui n'est évidemment pas le cas quand on le fait comme ça. Donc, je voudrais toujours savoir s'il y a une meilleure façon ...

Répondre

2

Vous pouvez utiliser le pub(restricted) privacy nouvellement stabilisé.

Cela vous permettra d'exposer les types/fonctions à un arbre de module limité, par ex.

pub struct GiantStruct { /* */ } 

impl GiantStruct { 
    // Only visible to functions in the same crate 
    pub(crate) fn new() -> GiantStruct { /* */ }; 

    // this method needs to be called from outside of the crate. 
    pub fn do_stuff(/* */) { /* */ }; 
} 

Ou vous pouvez l'appliquer à des champs sur votre GiantStruct pour vous permettre de le créer à partir GiantStructBuilder:

pub struct GiantStruct { 
    pub(crate) my_field: u32, 
} 

Au lieu de crate vous pouvez également utiliser super pour indiquer qu'il est uniquement public au module parent .