# Why doesn’t Julia offer built-in privacy/encapsulation features?

**URL:** <https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666>\
**Category:** General Usage\
**Tags:** question, internals, encapsulation, privacy\
**Created:** [January 11, 2025, 9:36am UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666 "2025-01-11T09:36:31Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![younes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/younes/32/208506_2.png) [@younes](https://discourse.julialang.org/u/younes)\
**Post date:** [January 11, 2025, 9:36am UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666/1 "2025-01-11T09:36:31Z")

</div>

I would like to understand Julia’s rationale for not including a language-level _ **privacy** _ feature: a way to _ **truly** _ protect the internal state from outside access.

I’m aware that we can use closures to emulate encapsulation, but that’s cumbersome, and it’s not really the same as a built-in mechanism. I’ve often heard the “We’re All Adults Here” mindset mentioned, but I find that unconvincing; even experienced developers introduce critical bugs—memory-safety issues in C/C++ being just one high-profile example. Of course, Julia’s garbage collection helps prevent memory corruption, but direct messing with internal structs can still lead to logical or invariant-breaking bugs.

So, is there a deeper reason why Julia can’t (or shouldn’t) offer **an opt-in privacy model**?

I’d personally find it fair if those who want stricter encapsulation “pay” with potential performance or debugging complexity. But I’d love to hear the community’s thoughts on whether this is feasible or if it conflicts too deeply with Julia’s design goals around metaprogramming and introspection.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [January 11, 2025, 9:53am UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666/2 "2025-01-11T09:53:55Z")

</div>

I found this weird, too, at the beginning. Now I believe:

- the Julia status quo is preferable to what the stricter, “object-oriented”, languages have
- the status quo will improve further

The benefits exist for interactive usage, e.g., in exploration in the REPL, also testing, in some cases. This is huge and I don’t think any experienced user is willing to give it up.

The drawback is packages being able to trespass on the internals of the Julia implementation, or the internals of other packages, leading to breakage on a new release of such an intruded-on dependency. IMO the problem isn’t being able to poke at internals of dependencies on its own, the problem is being able to do that while failing to pin the version of that dependency properly in Project.toml.

So I expect this will be solved in a best-of-both worlds manner; now that we have `public` and `Base.ispublic`, the required validation can happen programmatically. It’s possible to:

- have a check disallowing the registration of package release
- have a check for an editor linter
- implement an actual strict check as part of a strict mode for Julia: [Add `strict` mechanism for opting into stricter subsets of the language · Issue #54903 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/54903)

None of this is implemented, yet, though, AFAIK.

Another relevant issue is [Disallow access to internals (unless overridden) · Issue #52314 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/52314)

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [January 11, 2025, 11:19am UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666/3 "2025-01-11T11:19:54Z")

</div>

It’s not only structs, but also functions/methods. Nothing prevents you from making e.g. `Int` an iterator to iterate through the numbers below (if one believes in the von Neumann definition of the natural numbers):

```julia
function Base.iterate(n::Int, state=nothing)
    isnothing(state) && return n<=0 ? nothing : (0, (1,n))
    next, lim = state
    next ≥ lim && return nothing
    return (next, (next+1, lim))
end
Base.IteratorSize(::Type{Int}) = Base.HasLength()
Base.length(i::Int) = i
julia> collect(5)
5-element Vector{Int64}:
 0
 1
 2
 3
 4

```

However, a lot of things will be messed up by this fancy trick, since they may rely on the default behaviour, that `collect(5)` returns a 0-dimensional `Array` containing `5`.

The same goes for every method in every package. Anyone can replace any method. There is work underway to make it possible to “freeze” functions so that methods can’t be overwritten or added.

---

<div class="post-metadata">

**Author:** ![Ronis\_BR](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ronis_br/32/50999_2.png) [@Ronis\_BR](https://discourse.julialang.org/u/Ronis_BR)\
**Post date:** [January 11, 2025, 2:04pm UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666/4 "2025-01-11T14:04:24Z")

</div>

This feature and a way to describe an API and force it on the implementation is the two language features I miss the most.

Edit: I am not considering small binaries / AOT / creation of libraries a language feature 😃

---

<div class="post-metadata">

**Author:** ![GHTaarn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ghtaarn/32/216007_2.png) [@GHTaarn](https://discourse.julialang.org/u/GHTaarn)\
**Post date:** [January 11, 2025, 2:10pm UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666/5 "2025-01-11T14:10:09Z")

</div>

> [@younes](#):
>
> I’m aware that we can use closures to emulate encapsulation,

Hopefully you are aware that closures provide only marginally more privacy than structs, e.g.:

```julia-repl
julia> f(a) = () -> a
f (generic function with 1 method)

julia> b = f([55,77])
#3 (generic function with 1 method)

julia> b()
2-element Vector{Int64}:
 55
 77

julia> b.a[1]=0
0

julia> b()
2-element Vector{Int64}:
  0
 77

```

but AFAIK, this behaviour is undocumented and could change in future versions.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [January 11, 2025, 2:28pm UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666/6 "2025-01-11T14:28:12Z")

</div>

> [@younes](#):
>
> direct messing with internal structs can still lead to logical or invariant-breaking bugs

It also lets you extend behavior without waiting for the public API to allow it, and it’s often not a reasonable expectation for the public API to irreversibly support something that you may not want for long. This is how third party libraries can pull off static type inference or compiler plugins in a typical Julia process. But as you said, this is exceptional; for the most part we are heavily incentivized to not rely on things that can break on minor releases, hence the strong encouragement of documentation, leaning toward documenting methods instead of fields, and more recently a formal specifier of `public` global names (so not public fields, or rather properties). The more common usage of internals is interactive reflection without needing to write extra API from a reflection library or resort to undefined behavior. Historically, the “who needs access modifiers, we’re all adults” philosophy is standard in popular, interactive-first, dynamically typed languages preceding Julia e.g. Smalltalk, MATLAB, Python, R. Julia also cannot share the access modification of OOP languages that have class encapsulation; we can’t nest private types in other types. If we couldn’t access types with non-`public` global names, they’d be useless.

While it’s not true access modification, you can also make it harder for people to access fields by overloading `getproperty` and, for mutables, `setproperty!`. That forces them to resort to `getfield`/`setfield!` instead of using dot syntax.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [January 11, 2025, 2:50pm UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666/7 "2025-01-11T14:50:34Z")

</div>

There’s `propertynames` for marking a property as public. It defaults to making all fields be public properties, sadly.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [January 11, 2025, 2:53pm UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666/8 "2025-01-11T14:53:04Z")

</div>

Good catch, I think you’re refering to `propertynames` though. Does that mean `hasproperty` can be used for validation like `ispublic`?

---

<div class="post-metadata">

**Author:** ![dlfivefifty](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlfivefifty/32/1959_2.png) [@dlfivefifty](https://discourse.julialang.org/u/dlfivefifty)\
**Post date:** [January 11, 2025, 3:57pm UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666/9 "2025-01-11T15:57:43Z")

</div>

I don’t think you can “truly” protect internal state from outside access in a compiled language. You can always convert to a `Ptr` and access/modify data manually. So privacy is a question of programming convenience, not of actual safety.

So with that in mind: the benefits of a strict enforcement at compile time versus just telling users “don’t do this” is marginal.

In my own code I violate the “don’t do this” all the time: sometimes I need an internal function and I just don’t want to take the time to copy-and-paste it, or I worry that any improvements in future versions will be missed out. This does make my packages somewhat brittle, which is not great, but CI in Julia is very effective at catching bugs that result from this.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 11, 2025, 5:10pm UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666/10 "2025-01-11T17:10:12Z")

</div>

> [@younes](#):
>
> So, is there a deeper reason why Julia can’t (or shouldn’t) offer **an opt-in privacy model**?

@StefanKarpinski’s post in a related thread may give some insight into the underlying philosophy: [Private states in Julia modules - #19 by StefanKarpinski](https://discourse.julialang.org/t/private-states-in-julia-modules/1312/19)

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [January 11, 2025, 6:57pm UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666/11 "2025-01-11T18:57:41Z")

</div>

> [@dlfivefifty](#):
>
> This does make my packages somewhat brittle

I am having trouble right now with wrapping a C++ library where too much of attributes are made private. As you have said, it’s possible to circumvent that by taking raw pointers etc. and it would be much more brittle than in Julia, I think. So, I’d say the contrary is true: if you end up needing to break the rules, with C++ approach it’ll be inherently brittle (dependent on platform, compiler conventions etc.) while with “don’t do this” approach it may be done reasonably robust.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [January 11, 2025, 10:54pm UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666/12 "2025-01-11T22:54:37Z")

</div>

> [@Benny](#):
>
> Does that mean `hasproperty` can be used for validation like `ispublic`?

Not in practice, at least not in general. All fields are declared as public properties by default, and it’s actually kinda rare to define a `propertynames`method for one’s type, so `hasproperty` will usually answer `true` even if the property isn’t supposed to be public 😕

---

<div class="post-metadata">

**Author:** ![younes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/younes/32/208506_2.png) [@younes](https://discourse.julialang.org/u/younes)\
**Post date:** [January 13, 2025, 3:15pm UTC](https://discourse.julialang.org/t/why-doesn-t-julia-offer-built-in-privacy-encapsulation-features/124666/13 "2025-01-13T15:15:00Z")

</div>

I must admit, this was a very enlightening discussion where experiences, opinions, and history all came together!  
Thank you all for your feedback!
