public/protected/private is an unnecessary feature

Apologies for the unoriginal OOP example, but: Suppose class Car implements interface Vehicle. We'll ignore point 3, and focus on point 4.

Since Car can't restrict subclasses to only use an interface, any subclasses can violate Car's internal invariants.

So either Car should disallow inheritance (always an option by simply not exposing the Car type at all, as in point 2), or Car needs another way to define an interface that will take effect on subclasses.

That other way to define an interface which works for subclasses is the access modifiers: public, protected, and private. By marking members as private, Car can force subclasses to only use a specific interface to interact with Car, an interface composed of exactly and only those members which are public and protected.

But this is absurd: Why do we have two ways to define an interface?

Wouldn't it be better for Car to be able to force subclasses to only use Car through a specific interface? There'd be no loss in functionality; Car could still have separate interfaces for instantiators and subclasses. We'd just define those interfaces with the same mechanism, instead of using one mechanism for instantiators and another for subclasses.

Access modifiers were originally invented in Simula. As far as I can tell from extensive research, the inventors and users at that time simply didn't realize that access modifiers duplicated the interface-defining features that were already available: virtual methods and subtyping, which together are sufficient to define interfaces in Simula.

It's important to realize that, in the absence of inheritance, access modifiers provide no additional implementation-hiding power if you have interfaces. Remember point 2 from above; we don't need protected/private to hide the implementation details of a class.

Access modifiers were useful in Simula, of course, given that Simula invented and heavily used inheritance, so they needed to find some way to protect the implementation internals of base classes.

But other means could have been used, which reused the existing interface abilities of Simula. For example, Car could specify in the definition of Car that when Car is subclassed, only the fields declared in the base class Vehicle are available to the subclass.

Alas, as far as I can tell, they just simply didn't realize the possibility. And thus we've ended up with the unnecessary duplicate feature of access modifiers, carried on into language after language for the sake of backwards-compatibility.

Of course, we can still make things better in the future, by just not using access modifiers. If your class isn't available to be subclassed (say, because it's final), and you're restricting construction of it as in point 2 above, then there's absolutely no need to annotate it with access modifiers. Protection of the internals of the class can, and should, be achieved through defining an interface.

If you do really want to inherit from a non-abstract class... well, don't. Use composition instead. Inheritance was a hack in the first place.