This question already has answers here:
Interface naming in Java [closed]
(11 answers)
Closed 7 years ago.
How do you name different classes / interfaces you create?
Sometimes I don't have implementation information to add to the implementation name - like interface FileHandler and class SqlFileHandler.
When this happens I usually name the interface in the "normal" name, like Truck and name the actual class TruckClass.
How do you name interfaces and classes in this regard?
Name your Interface what it is. Truck. Not ITruck because it isn't an ITruck it is a Truck.
An Interface in Java is a Type. Then you have DumpTruck, TransferTruck, WreckerTruck, CementTruck, etc that implements Truck.
When you are using the Interface in place of a sub-class you just cast it to Truck. As in List<Truck>. Putting I in front is just Hungarian style notation tautology that adds nothing but more stuff to type to your code.
All modern Java IDE's mark Interfaces and Implementations and what not without this silly notation. Don't call it TruckClass that is tautology just as bad as the IInterface tautology.
If it is an implementation it is a class. The only real exception to this rule, and there are always exceptions, could be something like AbstractTruck. Since only the sub-classes will ever see this and you should never cast to an Abstract class it does add some information that the class is abstract and to how it should be used. You could still come up with a better name than AbstractTruck and use BaseTruck or DefaultTruck instead since the abstract is in the definition. But since Abstract classes should never be part of any public facing interface I believe it is an acceptable exception to the rule. Making the constructors protected goes a long way to crossing this divide.
And the Impl suffix is just more noise as well. More tautology. Anything that isn't an interface is an implementation, even abstract classes which are partial implementations. Are you going to put that silly Impl suffix on every name of every Class?
The Interface is a contract on what the public methods and properties have to support, it is also Type information as well. Everything that implements Truck is a Type of Truck.
Look to the Java standard library itself. Do you see IList, ArrayListImpl, LinkedListImpl? No, you see List and ArrayList, and LinkedList. Here is a nice article about this exact question. Any of these silly prefix/suffix naming conventions all violate the DRY principle as well.
Also, if you find yourself adding DTO, JDO, BEAN or other silly repetitive suffixes to objects then they probably belong in a package instead of all those suffixes. Properly packaged namespaces are self documenting and reduce all the useless redundant information in these really poorly conceived proprietary naming schemes that most places don't even internally adhere to in a consistent manner.
If all you can come up with to make your Class name unique is suffixing it with Impl, then you need to rethink having an Interface at all. So when you have a situation where you have an Interface and a single Implementation that is not uniquely specialized from the Interface you probably don't need the Interface in most cases.
However, in general for maintainability, testability, mocking, it's best practice to provide interfaces. See this answer for more details.
Also Refer this interesting article by Martin Fowler on this topic of InterfaceImplementationPair
I've seen answers here that suggest that if you only have one implementation then you don't need an interface. This flies in the face of the Depencency Injection/Inversion of Control principle (don't call us, we'll call you!).
So yes, there are situations in which you wish to simplify your code and make it easily testable by relying on injected interface implementations (which may also be proxied - your code doesn't know!). Even if you only have two implementations - one a Mock for testing, and one that gets injected into the actual production code - this doesn't make having an interface superfluous. A well documented interface establishes a contract, which can also be maintained by a strict mock implementation for testing.
in fact, you can establish tests that have mocks implement the most strict interface contract (throwing exceptions for arguments that shouldn't be null, etc) and catch errors in testing, using a more efficient implementation in production code (not checking arguments that should not be null for being null since the mock threw exceptions in your tests and you know that the arguments aren't null due to fixing the code after these tests, for example).
Dependency Injection/IOC can be hard to grasp for a newcomer, but once you understand its potential you'll want to use it all over the place and you'll find yourself making interfaces all the time - even if there will only be one (actual production) implementation.
For this one implementation (you can infer, and you'd be correct, that I believe the mocks for testing should be called Mock(InterfaceName)), I prefer the name Default(InterfaceName). If a more specific implementation comes along, it can be named appropriately. This also avoids the Impl suffix that I particularly dislike (if it's not an abstract class, OF COURSE it is an "impl"!).
I also prefer "Base(InterfaceName)" as opposed to "Abstract(InterfaceName)" because there are some situations in which you want your base class to become instantiable later, but now you're stuck with the name "Abstract(InterfaceName)", and this forces you to rename the class, possibly causing a little minor confusion - but if it was always Base(InterfaceName), removing the abstract modifier doesn't change what the class was.
The name of the interface should describe the abstract concept the interface represents. Any implementation class should have some sort of specific traits that can be used to give it a more specific name.
If there is only one implementation class and you can't think of anything that makes it specific (implied by wanting to name it -Impl), then it looks like there is no justification to have an interface at all.
I tend to follow the pseudo-conventions established by Java Core/Sun, e.g. in the Collections classes:
List - interface for the "conceptual" object
ArrayList - concrete implementation of interface
LinkedList - concrete implementation of interface
AbstractList - abstract "partial" implementation to assist custom implementations
I used to do the same thing modeling my event classes after the AWT Event/Listener/Adapter paradigm.
The standard C# convention, which works well enough in Java too, is to prefix all interfaces with an I - so your file handler interface will be IFileHandler and your truck interface will be ITruck. It's consistent, and makes it easy to tell interfaces from classes.
I like interface names that indicate what contract an interface describes, such as "Comparable" or "Serializable". Nouns like "Truck" don't really describe truck-ness -- what are the Abilities of a truck?
Regarding conventions: I have worked on projects where every interface starts with an "I"; while this is somewhat alien to Java conventions, it makes finding interfaces very easy. Apart from that, the "Impl" suffix is a reasonable default name.
Some people don't like this, and it's more of a .NET convention than Java, but you can name your interfaces with a capital I prefix, for example:
IProductRepository - interface
ProductRepository, SqlProductRepository, etc. - implementations
The people opposed to this naming convention might argue that you shouldn't care whether you're working with an interface or an object in your code, but I find it easier to read and understand on-the-fly.
I wouldn't name the implementation class with a "Class" suffix. That may lead to confusion, because you can actually work with "class" (i.e. Type) objects in your code, but in your case, you're not working with the class object, you're just working with a plain-old object.
I use both conventions:
If the interface is a specific instance of a a well known pattern (e.g. Service, DAO), then it may not need an "I" (e.g UserService, AuditService, UserDao) all work fine without the "I", because the post-fix determines the meta pattern.
But, if you have something one-off or two-off (usually for a callback pattern), then it helps to distinguish it from a class (e.g. IAsynchCallbackHandler, IUpdateListener, IComputeDrone). These are special purpose interfaces designed for internal use, occasionally the IInterface calls out attention to the fact that an operand is actually an interface, so at first glance it is immediately clear.
In other cases you can use the I to avoid colliding with other commonly known concrete classes (ISubject, IPrincipal vs Subject or Principal).
TruckClass sounds like it were a class of Truck, I think that recommended solution is to add Impl suffix. In my opinion the best solution is to contain within implementation name some information, what's going on in that particular implementation (like we have with List interface and implementations: ArrayList or LinkedList), but sometimes you have just one implementation and have to have interface due to remote usage (for example), then (as mentioned at the beginning) Impl is the solution.
Related
I'm semi-familiar with Java and came across something in Effective Java(2017) that didn't make much sense to me.
Below is a piece from the book. (item 18)
Unlike method invocation, inheritance violates encapsulation. In other words, a subclass depends on the implementation details of its superclass for its proper function. The superclass's implementation may change from release to release, and if it does, the subclass may break, even though its code has not been touched. As a consequence, a subclass must evolve in tandem with its superclass, unless the superclass's authors have designed and documented it specifically for the purpose of being extended.
I understand composition may be favored over inheritance in some cases and understood other parts of item 18. However, I find it hard to understand how the composition method prevents the problem mentioned in the paragraph above(dependency on implementation details) - as the author speaks as though composition is better than inheritance because of this. Later in the chapter, Bloch gives an example of a custom Set implementation where he uses a Forwarding Class(which is obviously dependent on the Set interface details). One could argue the Set interface doesn't change as often but in practice changes in the interface may as well cause the Wrapper Class to break(note the book gives an example via Forwarding Class and Wrapper Class).
I guess it makes sense if Bloch meant composition is relatively safer than inheritance because class implementations change more often than interfaces. However, I think there is still a dependency issue between Wrapper Class and Interface, and am confused on why the author didn't mention this more clearly.
Am I mistaken in thinking like this?
(In addition, I'm not sure what encapsulation has to do with this. My understanding of encapsulation is hiding variables using private..)
You should actually provide more on the examples i.e. "Later in the chapter, Bloch gives an example of a custom Set implementation"
Basically the inheritance is that the child class will be affected by the change of parent class. See code below:
public class Baby extends Human{
}
In the code above, if Human implement another public or protected method, Baby will be forced to automatically inherit it. It is quite stringent.
But for composition, a change in the Owner object does not really require a change in the child object, and vice versa up to a certain degree.
public class Human{
private Baby baby;
}
In the code above, Human can have any implementation that may not impact Baby and vice versa. There is more leeway for designing what Baby and Human can do. They can be entirely having lots of different properties and methods.
Ok so I looked up what #LeiYang recommended and came to realize the my question wasn't valid. The given paragraph states "a subclass depends on the implementation details of its superclass for its proper function" - which Object Composition would have no problem with, as it merely makes use of provided methods as is(without overriding). Therefore Object Composition doesn't violate encapsulation and is relatively stable compared to Inheritance.
From this blog:
I’ve been programming in Java for over 16 years and teaching it for nearly half that time. So it’s going to take a little practice to stop repeating this sentence: “Interfaces may only contain methods that are public and abstract.” As of Java 8, that statement is no longer true. It is now possible to add both instance and static methods to Java interfaces.
Does new C# version allow this also or will in some intended future?
I always felt Interface was good in theory but in practice caused many kind of maintenance nightmare on your interface consumers as described in the article.
Update : I'm also interested by the critics, all the more if you have read the author's article especially about abstract class alternative as not solving real world problem.
It is to the implementing class in C# to determine the scope of the method or property implemented. C# knows implicit and explicit interface implementation, which helps to set the scope of the method. (You can create a secondary method or property that has the wanted scope (internal, private, protected).
Static interface methods are not possible in C# and I wonder why you would want that. Static methods are bound to the type and not to the instance, so you can't call this.StaticMethod for example. That makes defining them on interfaces useless.
And default methods are just... horrible. Make an abstract class. Period.
I was just looking at the Java Hamcrest code on GitHub, and noticed they employed a strategy that seemed unintuitive and awkward, but it got me wondering if I'm missing something.
I noticed in the HamCrest API that there is an interface Matcher and an abstract class BaseMatcher. The Matcher interface declares this method, with this javadoc:
/**
* This method simply acts a friendly reminder not to implement Matcher directly and
* instead extend BaseMatcher. It's easy to ignore JavaDoc, but a bit harder to ignore
* compile errors .
*
* #see Matcher for reasons why.
* #see BaseMatcher
* #deprecated to make
*/
#Deprecated
void _dont_implement_Matcher___instead_extend_BaseMatcher_();
Then in BaseMatcher, this method is implemented as follows:
/**
* #see Matcher#_dont_implement_Matcher___instead_extend_BaseMatcher_()
*/
#Override
#Deprecated
public final void _dont_implement_Matcher___instead_extend_BaseMatcher_() {
// See Matcher interface for an explanation of this method.
}
Admittedly, this is both effective and cute (and incredibly awkward). But if the intention is for every class that implements Matcher to also extend BaseMatcher, why use an interface at all? Why not just make Matcher an abstract class in the first place and have all other matchers extend it? Is there some advantage to doing it the way Hamcrest has done it? Or is this a great example of bad practice?
EDIT
Some good answers, but in search of more detail I'm offering a bounty. I think that the issue of backwards / binary compatibility is the best answer. However, I'd like to see the issue of compatibility elaborated on more, ideally with some code examples (preferably in Java). Also, is there a nuance between "backwards" compatibility and "binary" compatibility?
FURTHER EDIT
January 7, 2014 -- pigroxalot provided an answer below, linking to
this comment on Reddit by the authors of HamCrest. I encourage everyone to read it, and if you find it informative, upvote pigroxalot's answer.
EVEN FURTHER EDIT
December 12, 2017 -- pigroxalot's answer was removed somehow, not sure how that happened. It's too bad... that simple link was very informative.
The git log has this entry, from December 2006 (about 9 months after the initial checkin):
Added abstract BaseMatcher class that all Matchers should extend. This allows for future API compatability [sic] as the Matcher interface evolves.
I haven't tried to figure out the details. But maintaining compatibility and continuity as a system evolves is a difficult problem. It does mean that sometimes you end up with a design that you would never, ever, ever have created if you had designed the whole thing from scratch.
But if the intention is for every class that implements Matcher to also extend BaseMatcher, why use an interface at all?
It's not exactly the intent. Abstract base classes and interfaces provide entirely different 'contracts' from an OOP perspective.
An interface is a communication contract. An interface is implemented by a class to signify to the world that it adheres to certain communication standards, and will give a specific type of result in response to a specific call with specific parameters.
An abstract base class is an implementation contract. An abstract base classes is inherited by a class to provide functionality that is required by the base class but left for the implementer to provide.
In this case, both overlap, but this is merely a matter of convenience - the interface is what you need to implement, and the abstract class is there to make implementing the interface easier - there is no requirement whatsoever to use that base class to be able to offer the interface, it's just there to make it less work to do so. You are in no way limited in extending the base class for your own ends, not caring about the interface contract, or in implementing a custom class implementing the same interface.
The given practice is actually rather common in old-school COM/OLE code, and other frameworks facilitating inter-process communications (IPC), where it becomes fundamental to separate implementation from interface - which is exactly what is done here.
I think what happened is that initially a Matcher API was created in the form of an interface.
Then while implementing the interface in various ways a common code base was discovered which was then refactored out into the BaseMatcher class.
So my guess is that the Matcher interface was retained as it is part of the initial API and the descriptive method was then added as a reminder.
Having searched through the code, I found that the interface could easily by done away with as it is ONLY implemented by BaseMatcher and in 2 test units which could easily be changed to use BaseMatcher.
So to answer your question - in this particular case there is no advantage to doing it this way, besides not breaking other peoples implementations of Matcher.
As to bad practice ? In my opinion it is clear and effective - so no I don't think so, just a little odd :-)
Hamcrest provides matching, and matching only. It is a tiny niche market but they appear to be doing it well. Implementations of this Matcher interface are littered across a couple unit testing libraries, take for example Mockito's ArgumentMatcher and across a silly great amount of tiny anonymous copy-paste implementations in unit tests.
They want to be able to extend the Matcher with a new method without breaking all of those existing implementing classes. They would be hell to upgrade. Just imagine suddenly having all your unittest classes showing angry red compile errors. The anger and annoyance would kill hamcrest's niche market in one quick swoop. See http://code.google.com/p/hamcrest/issues/detail?id=83 for a small taste of that. Also, a breaking change in hamcrest would divide all versions of libraries that use Hamcrest into before and after the change and make them mutually exclusive. Again, a hellish scenario. So, to keep some freedom, they need Matcher to be an abstract base class.
But they are also in the mocking business, and interfaces are way easier to mock than base classes. When the Mockito folks unit test Mockito, they should be able to mock the matcher. So they also need that abstract base class to have a Matcher interface.
I think they have seriously considered the options and found this to be the least bad alternative.
There is an interesting discussion about it here. To quote nat_pryce:
Hi. I wrote the original version of Hamcrest, although Joe Walnes
added this wierd method to the base class.
The reason is because of a peculiarity of the Java language. As a
commenter below said, defining Matcher as a base class would make it
easier to extend the library without breaking clients. Adding a method
to an interface stops any implementing classes in client code from
compiling, but new concrete methods can be added to an abstract base
class without breaking subclasses.
However, there are features of Java that only work with interfaces, in
particular java.lang.reflect.Proxy.
Therefore, we defined the Matcher interface so that people could write
dynamic implementations of Matcher. And we provided the base class for
people to extend in their own code so that their code would not break
as we added more methods to the interface.
We have since added the describeMismatch method to the Matcher
interface and client code inherited a default implementation without
breaking. We also provided additional base classes that make it easier
to implement describeMismatch without duplicating logic.
So, this is an example of why you can't blindly follow some generic
"best practice" when it comes to design. You have to understand the
tools you're using and make engineering trade-offs within that
context.
EDIT: separating the interface from the base class also helps one cope
with the fragile base class problem:
If you add methods to an interface that is implemented by an abstract
base class, you may end up with duplicated logic either in the base
class or in subclasses when they are changed to implement the new
method. You cannot change the base class to remove that duplicated
logic if doing so changes the API provided to subclasses, because that
will break all subclasses -- not a big problem if the interface and
implementations are all in the same codebase but bad news if you're a
library author.
If the interface is separate from the abstract base class -- that is,
if you distinguish between users of the type and implementers of the
type -- when you add methods to the interface you can add a default
implementation to the base class that will not break existing
subclasses and introduce a new base class that provides a better
partial implementation for new subclasses. When someone comes to
change existing subclasses to implement the method in a better way,
then can choose to use the new base class to reduce duplicated logic
if it makes sense to do so.
If the interface and base class are the same type (as some have
suggested in this thread), and you then want to introduce multiple
base classes in this way, you're stuck. You can't introduce a new
supertype to act as the interface, because that will break client
code. You can't move the partial implementation down the type
hierarchy into a new abstract base class, because that will break
existing subclasses.
This applies as much to traits as Java-style interfaces and classes or
C++ multiple inheritance.
Java8 now allows new methods to be added to an interface if they contains default implementations.
interface Match<T>
default void newMethod(){ impl... }
this is a great tool that gives us a lot of freedom in interface design and evolution.
However, what if you really really want to add an abstract method that has no default implementation?
I think you should just go ahead and add the method. It'll break some existing codes; and they will have to be fixed. Not really a big deal. It probably beats other workarounds that preserve binary compatibility at the cost of screwing up the whole design.
But if the intention is for every class that implements Matcher to
also extend BaseMatcher, why use an interface at all? Why not just
make Matcher an abstract class in the first place and have all other
matchers extend it?
By separating interface and implementation (abstract class is still an implementation) you comply with Dependency Inversion Principle. Do not confuse with dependency injection, nothing in common. You might notice that, in Hamcrest interface is kept in hamcrest-api package, while abstract class is in hamcrest-core. This provides low coupling, because implementation depends only on interfaces but not on other implementation. A good book on this topic is: Interface Oriented Design: With Patterns.
Is there some advantage to doing it the way Hamcrest has done it? Or
is this a great example of bad practice?
The solution in this example looks ugly. I think comment is enough. Making such stub methods is redundant. I wouldn't follow this approach.
In a lecture on Java, a computer science professor states that Java interfaces of a class are prototypes for public methods, plus descriptions of their behaviors.
(Source https://www.youtube.com/watch?v=-c4I3gFYe3w #8:47)
And at 8:13 in the video he says go to discussion section with teaching assistants to learn what he means by prototype.
What does "prototype" mean in Java in the above context?
I think the use of the word prototype in this context is unfortunate, some languages like JavaScript use something called prototypical inheritance which is totally different than what is being discussed in the lecture. I think the word 'contract' would be more appropriate. A Java interface is a language feature that allows the author of a class to declare that any concrete implementations of that class will provide implementations of all methods declared in any interfaces they implement.
It is used to allow Java classes to form several is-a relationships without resorting to multiple inheritance (not allowed in Java). You could have a Car class the inherits from a Vehicle class but implements a Product interface, therefor the Car is both a Vehicle and a Product.
What does "prototype" mean in Java in the above context?
The word "prototype" is not standard Java terminology. It is not used in the JLS, and it is not mentioned in the Java Tutorial Glossary. In short there is no Java specific meaning.
Your lecturer is using this word in a broader sense rather than a Java-specific sense. In fact, his usage matches "function prototype" as described in this Wikipedia page.
Unfortunately, the "IT English" language is full of examples where a word or phrase means different (and sometimes contradictory) things in different contexts. There are other meanings for "template" that you will come across in IT. For instance:
In C++ "template" refers to what Java calls a generic class or method.
In Javascript, an object has a "template" attribute that gives the objects methods.
More generally, template-based typing is an alternative (more dynamic) way of doing OO typing.
But the fact that these meanings exist does not mean that your lecturer was wrong to refer to interface method signatures as "templates".
"prototype" is not the the best/right terminus to be used. interfaces are more like "contracts", that implementing classes have to fulfill.
The method's heads/definitions will have to be implemented in the implementing class (using implements keyword in the class head/class definition/public class xy implements ...).
I guess this naming conventions leave much room for many ideological debates.
Or the author had some sort of a mental lapsus and mapped the construct of prototypical inheritance from javascript into java in his mind somehow.
Interfaces are not prototypes for classes in Java.
In languages like C & C++, which compiles to machine code sirectly, compiler should be aware of the nature of any identifier (variable/class/functions) before they are references anywhere in the program. That mean those languages require to know the nature of the identifier to generate a machine code output that is related to it.
In simple words, C++ compiler should be aware of methods and member of a class before that class is used anywhere in the code. To accomplish that, you should define the class before the code line where it is used, or you should at least declare its nature. Declaring only the nature of a function or a class creates a 'prototype'.
In Java, an 'interface' is something like description of a class. This defines what all methods a particular kind of class should mandatory have. You can then create classes that implements those interface. Main purpose that interfaces serve in java is the possibility that a Variable declared as of a particular interface type can hold objects of any class that implements the object.
He tells it in C/C++ way, let me explain, in C++ you can define prototypes for methods at the header files of classes so that other classes can recognize these methods, also in C where there is no class concept, you can define prototypes at the beginning of file and then at somewhere in same file you can implement these prototypes, so that methods can be used even before their implementation is provided. So in Java interfaces provide pretty much same way, you can define prototypes for methods(method headers) that will be implemented by classes that implement this interface.
In a lecture on Java, a computer science professor states that:
Java interfaces of a class are:
1. are prototypes for public methods,
2. plus descriptions of their behaviors.
For 1. Is ok: - yes, they are prototypes for implemented public methods of a class.
For 2. This part could be a little bit tricky. :)
why?
we know: interface definition (contain prototypes), but doesn't define (describe) methods behavior.
computer science professor states: "... plus descriptions of their behaviors.". This is correct only if we look inside class that implements that interface (interface implementation = prototype definitions or descriptions).
Yes, a little bit tricky to understand :)
Bibliography:
Definition vs Description
Context-dependent
Name visibility - C++ Tutorials
ExtraWork:
Note: not tested, just thinking! :)
C++:
// C++ namespace just with prototypes:
// could be used like interface similar with Java?
// hm, could we then define (describe) prototypes?
// could we then inherit namespace? :)
namespace anIntf{
void politeHello(char *msg);
void bigThankYou();
}
Prototypes provide the signatures of the functions you will use
within your code. They are somewhat optional, if you can order
your code such that you only use functions that are previously
defined then you can get away without defining them
Below a prototype for a function that sums two integers is given.
int add(int a, int b);
I found this question because i have the same impression as that teacher.
In early C (and C++ i think) a function, for example "a" (something around lexic analysis or syntactic, whatever) can not be called, for example inside main, before it's declaration, because the compiler doesn't know it (yet).
The way to solve it was, either to declare it before it's usage (before main in the example), or to create a prototype of it (before main in the example) which just specifies the name, return values and parameters; but not the code of the function itself, leaving this last one for wherever now is placed even after it's called.
These prototypes are basically the contents of the include (.h) files
So I think is a way to understand interfaces or the way they say in java "a contract" which states the "header" but not the real body, in this case of a class or methods
In java, is there ever a case for allowing a non-abstract class to be extended?
It always seems to indicate bad code when there are class hierarchies. Do you agree, and why/ why not?
There are certainly times when it makes sense to have non-final concrete classes. However, I agree with Kent - I believe that classes should be final (sealed in C#) by default, and that Java methods should be final by default (as they are in C#).
As Kent says, inheritance requires careful design and documentation - it's very easy to think you can just override a single method, but not know the situations in which that method may be called from the base class as part of the rest of the implementation.
See "How do you design a class for inheritance" for more discussion on this.
I agree with Jon and Kent but, like Scott Myers (in Effective C++), I go much further. I believe that every class should be either abstract, or final. That is, only leaf classes in any hierarchy are really apt for direct instantiation. All other classes (i.e. inner nodes in the inheritance) are “unfinished” and should consequently be abstract.
It simply makes no sense for usual classes to be further extended. If an aspect of the class is worth extending and/or modifying, the cleaner way would be to take that one class and separate it into one abstract base class and one concrete interchangeable implementation.
there a good reasons to keep your code non-final. many frameworks such as hibernate, spring, guice depend sometimes on non-final classes that they extends dynamically at runtime.
for example, hibernate uses proxies for lazy association fetching.
especially when it comes to AOP, you will want your classes non-final, so that the interceptors can attach to it.
see also the question at SO
This question is equally applicable to other platforms such as C# .NET. There are those (myself included) that believe types should be final/sealed by default and need to be explicitly unsealed to allow inheritance.
Extension via inheritance is something that needs careful design and is not as simple as just leaving a type unsealed. Therefore, I think it should be an explicit decision to allow inheritance.
Your best reference here is Item 15 of Joshua Bloch's excellent book "Effective Java", called "Design and document for inheritance or else prohibit it". However the key to whether extension of a class should be allowed is not "is it abstract" but "was it designed with inheritance in mind". There is sometimes a correlation between the two, but it's the second that is important. To take a simple example most of the AWT classes are designed to be extended, even those that are not abstract.
The summary of Bloch's chapter is that interaction of inherited classes with their parents can be surprising and unpredicatable if the ancestor wasn't designed to be inherited from. Classes should therefore come in two kinds a) classes designed to be extended, and with enough documentation to describe how it should be done b) classes marked final. Classes in (a) will often be abstract, but not always. For
I disagree. If hierarchies were bad, there'd be no reason for object oriented languages to exist. If you look at UI widget libraries from Microsoft and Sun, you're certain to find inheritance. Is that all "bad code" by definition? No, of course not.
Inheritance can be abused, but so can any language feature. The trick is to learn how to do things appropriately.
In some cases you want to make sure there's no subclassing, in other cases you want to ensure subclassing (abstract). But there's always a large subset of classes where you as the original author don't care and shouldn't care. It's part of being open/closed. Deciding that something should be closed is also to be done for a reason.
I couldn't disagree more. Class hierarchies make sense for concrete classes when the concrete classes know the possible return types of methods that they have not marked final. For instance, a concrete class may have a subclass hook:
protected SomeType doSomething() {
return null;
}
This doSomething is guarenteed to be either null or a SomeType instance. Say that you have the ability to process the SomeType instance but don't have a use case for using the SomeType instance in the current class, but know that this functionality would be really good to have in subclasses and most everything is concrete. It makes no sense to make the current class an abstract class if it can be used directly with the default of doing nothing with its null value. If you made it an abstract class, then you would have its children in this type of hierarchy:
Abstract base class
Default class (the class that could have been non-abstract, only implements the protected method and nothing else)
Other subclasses.
You thus have an abstract base class that can't be used directly, when the default class may be the most common case. In the other hierarchy, there is one less class, so that the functionality can be used without making an essentially useless default class because abstraction just had to be forced onto the class.
Default class
Other subclasses.
Now, sure, hierarchies can be used and abused, and if things are not documented clearly or classes not well designed, subclasses can run into problems. But these same problems exist with abstract classes as well, you don't get rid of the problem just because you add "abstract" to your class. For instance, if the contract of the "doSomething()" method above required SomeType to have populated x, y and z fields when they were accessed via getters and setters, your subclass would blow up regardless if you used the concrete class that returned null as your base class or an abstract class.
The general rule of thumb for designing a class hierarchy is pretty much a simple questionaire:
Do I need the behavior of my proposed superclass in my subclass? (Y/N)
This is the first question you need to ask yourself. If you don't need the behavior, there's no argument for subclassing.
Do I need the state of my proposed superclass in my subclass? (Y/N)
This is the second question. If the state fits the model of what you need, this may be a canidate for subclassing.
If the subclass was created from the proposed superclass, would it truly be an IS-A relation, or is it just a shortcut to inherit behavior and state?
This is the final question. If it is just a shortcut and you cannot qualify your proposed subclass "as-a" superclass, then inheritance should be avoided. The state and logic can be copied and pasted into the new class with a different root, or delegation can be used.
Only if a class needs the behavior, state and can be considered that the subclass IS-A(n) instance of the superclass should it be considered to inherit from a superclass. Otherwise, other options exist that would be better suited to the purpose, although it may require a little more work up front, it is cleaner in the long run.
There are a few cases where we dont want to allow to change the behavior. For instance, String class, Math.
I don't like inheritance because there's always a better way to do the same thing but when you're making maintenance changes in a huge system sometimes the best way to fix the code with minimum changes is to extend a class a little. Yes, it's usually leads to a bad code but to a working one and without months of rewriting first. So giving a maintenance man as much flexibility as he can handle is a good way to go.