Trait-protected elements

Currently, all trait functions and types are public. Perhaps, more visibility modifiers could be put into place. One modifier that immediately comes to mind is a protected modifier, similar to Java's. See below:

trait A {
    pub(Self) fn protected_fn(); // or maybe another syntax
}

struct B;

impl A for B {
    pub(super) fn protected_fn() { // or for(super) or (for dyn A)
        
    }
}

In this case, A::protected_fun, would only allow its caller to originate within the struct itself, and from the A trait. Therefor, this can be used for replicating the idea of the abstract class from within traits.

Although, while speaking to other people on this idea, a few have suggested that encapsulation stay primitive to other languages, since Rust does not rely solely on OOP.

If this is something we want (personally I don't see the use case), please avoid using pub(foo) syntax — that should be reserved for actual visibility involving modules, not items.

Personally, I'm not sold on the idea of item-private items like Java. I would support a proposal to allow traits to have crate-private methods - implemented by users, but only callable in the original crate, which would better match with Rust's existing module-privacy style.

1 Like

Note that Rust absolutely supports encapsulation! Struct fields and all non-trait impl members are private-by-default, and only public within the modules below the given pub(in path).

What Rust doesn't have is type based encapsulation, where you say "only I and impls on Other can see this." Instead, you just put the impl Other within the modules that can see the item.

Additionally, Rust doesn't have mixins the way that superclass protected functions are. Instead of using (and abusing) OOP inheritance for code reuse via superclasses, Rust encourages you to encapsulate the partial functionality via either just using free functions or containing an instance (encapsulating a member field) of the struct data and functionality instead.

Java and similar rely on type-driven encapsulation because everything provided on a type must be in a single file. Rust allowing you to use multiple impl blocks for the same type allow it to solely use the simpler and yet more powerful module based privacy rules exclusively in order to encapsulate implementation details.

7 Likes