开发者

Why do so many foss libraries make their classes public and not final?

Before you jump on me with an obvious answer, let me qualify the question and say, not all classes are sub classable.

  • Sub classing should be a carefully thought out extra not a default property of all classes.
  • It could be argued classes should be final by default and not final if one really wants that.

I can think of many advantages for package private classes.

  • if the class is not really for my viewing and just a helper that i should consider a implementation detail, making it non public means it wont come up when i search for classes by name or implementations of an interface in my ide.
  • it also means that if everything but the exported interfaces are public examining the api while browsing the library jar files becomes much simpler as there is less noise. I no longer see internal implementation stuff.
  • there is no need to worry about sub classes outside your package.
  • for the users the practical benefit means that methods they need are probably also going to be grouped together under one interface/class rather than being scattered around in other public classes which means less cluter and there are less places to look and less handles too manage.

So why dont people 开发者_运维问答take advantage of these facilities ?


There are languages e.g. python in which everything is public and nothing is final. That doesn't mean they are living in hell and modules are impossible to use and maintain. Quite the contrary.

Software engineering is tricky. Many times we are fighint strawmen in our minds. That can be fun, we chase the ideal regardless of practical benefits - if we have the time. If you are a single person that's responsible for hundreds of classes, being a perfectionist will drive you crazy.


Basically, circumstances change. What you think is not subclassable now, may be required for subclassing later. A lot of more "fluffy"design choices (such as making a class final) are considered over engineering later when you find out that in fact you should be subclassing.

Most API designs take into account extendability.


In terms of whether classes should be final or not by default, it's a heavily debated point for which there's not really a "right" answer. Java chose to do it one way, C# another, different people think different languages got it right and wrong.

Personally, I like the way classes are extendible by default, if people want to make them final then they can, it's only a keyword away. But allowing sub classing just adds more flexibility in my view, sure I don't have to extend every non-final object under the sun but if I want to add some degree of specific behaviour then that option's there for me to do so. Yes, composition could be used (and indeed should be used in some cases) but that doesn't and shouldn't rule out sub classing as an option. There's many cases when the sub-classed object fulfils the is-a relationship with the parent, and in that case it's the right way to go. Admittedly though this has been misused in the past, even in the Java API (properties for instance is not really a hashtable.) But if you're trying to change the language to stop people being stupid - well, they'll always find a way around it!

As for making classes package private, for me this option would be far more useful if packages were hierarchical rather than flat. Yes, they're hierarchical in description but something declared package private in org.me can't be accessed from org.me.subpackage, which I often feel the need to do. Fortunately with the addition of superpackages we might see this option being better used!


  1. Your supposed advantages of libraries not supporting sub-classing is not backed by my experience.

  2. Java doesn't have delegation, thin subclasses are often used as adapters or method interceptors. It is more readable to do it in code than doing it by using a reflective proxy.

Things change. Software that can change is easier to work with. Sometimes this takes radical improvements like Java 8's default methods. These neatly fix adding methods to interfaces after the interfaces are widely used.


Well, this is just because thinking what should NOT be EVER extended takes lots of brain effort.

For most of small and medium-sized components and frameworks good guess is that to deprecate and keep the abused/overused method/class is easier and more user-friendly than thinking of most probable and some quite improbable usecases and still occasionally closing something which then needs some dirty delegation/decoration instead of simple extension.

On my practice only Java's Spring really bothered me with this kind of preventive closure (which results in a lot clearer API after several micro releases I think).

I had a quote of R. Martin on this matter here:

http://java.akraievoy.org/2009/03/openclosed-principle-strategic-closure.html


  • modifiers public and final are from different categories, putting them to single sentence is not a good start when you want to make things clear
  • as for final - requirements change and after some time you can find yourself in need to subclass some final class too, plus not all libraries/frameworks can crate proxies to final classes
  • as for package access - could make refactoring more complicated, but yes, if you produce some library, to not publish internal classes is a good "pattern"
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜