Intermediary between public and private members

6 points by nrposner


Say I were to have a

struct Foo { pub public: Bar, restricted: Qux }

where ‘restricted’ is some member variable which I want to be able to get, but not set, from outside of the struct methods. Normally, I would write a getter method

impl Foo { pub fn restricted(&self) -> &Qux { self.restricted }}

which isn’t very much typing, and probably I could generate these automatically with an IDE or a plugin.

But all the same, why not build this into the declaration syntax with a modifier in between private (implicit in Rust but some languages have it) and public? Maybe something like read so that we could have

struct Foo { x, read y, pub z }

Where x is genuinely private to the struct and can only be read or written by member functions, y can be read by anyone but not modified arbitrarily, and z can be read or written to by anyone?

This would need to distinguish between access and mutation of foo.y, which may not be trivial but doesn’t seem outwardly especially difficult.

I’m wondering if there are hidden gotchas here that make this a lot more complex from a language design perspective, or less ergonomic than I’m assuming. If not, it seems like a straightforward feature for future languages to implement, worth an extra keyword, I would think.

And if it it possible and desirable, what should the default be? It makes some sense to be that read-only is a more sensible default than full privacy if all three states are available.

Eager to hear people’s thoughts.

david_chisnall

C# and Objective-C have some syntactic sugar for synthesising accessor functions, which let you synthesise just the getter if you want a public getter and a private field. This works nicely and, in C#, the getters are almost always inlined and so are effectively free.

That said, I don’t really like this model of access control at all. Visibility specifiers are software engineering boundaries, not security boundaries. They indicate type invariants that are protected by code that enforces them, and stability for users of an interface. I strongly believe that the only two that make sense are public and package. Public things are part of an interface that should be stable. Package-private things are unstable and all code that touches them directly needs to be upgraded atomically.