Scala default visibility: missing private‑by‑default enforcement
0 reputation · 04 Aug 2025, 00:13 UTC
0 reputation · 04 Aug 2025, 00:13 UTC
In Scala, any class member without an explicit private, protected, or package‑specific modifier is public by default, meaning it is visible from any other code in the same or a different package.
Despite this, the Scala community has debated for years whether the language should adopt a private‑by‑default model to reduce accidental public APIs, but no decision has been finalized.
Developers therefore rely on conventions or custom linting tools to enforce stricter encapsulation, which can be inconsistent across projects and build pipelines.
Without a language‑level or compiler‑level enforcement, there is a risk that internal helpers or experimental fields become part of the public contract, complicating refactoring and versioning.
What mechanisms are currently available to warn about or block default‑public members? How can a project configure the compiler or tooling to enforce a private‑by‑default discipline? Are there active proposals to change the default visibility, and what would be the migration path?
31775 reputation · 04 Aug 2025, 06:06 UTC
Scala does not offer a compiler flag or language keyword to make members private-by-default. Any class member without an explicit private, protected, or package-private modifier is public by default, visible from any other code in the same or a different package. The language has discussed this trade-off for years, but no Scala Improvement Proposal has been adopted to change the default, not even in Scala 3.
The following compile-time tools can warn or block implicitly public members:
Wart.PublicInfer wart emits a warning when a member lacks an explicit visibility modifier. In sbt, enable it with wartremoverWarnings ++= Seq(Wart.PublicInfer).NoPublicMembers rule can be configured to error on missing modifiers, blocking compilation until each member is annotated. Enable via scalafixOnCompile := true and the required dependency.PublicFinalizer flags members that are publicly accessible without explicit marking, useful as a supplementary check.Typical migration path:
private or protected to every flagged member.Verification step: create a Scala class with a field that has no visibility modifier, run sbt wartremover with the PublicInfer wart enabled; a warning about PublicInfer should appear. For Scalafix, configure the rule as described and run sbt scalafix; the rule will suggest or enforce adding private/protected.
To refine the exact sbt, Maven, or Gradle setup and Scala version-specific flags, please specify your build tool and Scala version. This detail helps confirm the correct plugin keys and linter integration steps.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.