Question Details

No question body available.

Tags

java object-oriented

Answers (3)

October 7, 2025 Score: 5 Rep: 220,789 Quality: Medium Completeness: 80%

IMHO implementation inheritance is not an anti-pattern in general.

There are too many examples where this works well enough to ban this kind of inheritance dogmatically. You presented a few examples where the convenience wins over other aspects, and I could extend the list by several examples by myself, hence it should be clear that we talk about a trade-off, not a no-go.

So under which circumstances is this kind of inheritance ok, and when not?

I think the most important aspect here is to stick to a single dimension for a single inheritance tree.

What does that mean? It means, for example, not to mix a domain model dimension with technical dimensions.

For example, let's take your BaseDAO. Using inheritance for domain concepts, you can have classes like PersonDAO, DoctorDAO, or PrescriptionDAO, modeling the domain dimension.

But now lets assume you want to support different database systems, and you want special DAO classes for PostgreSQL, Oracle and maybe MongoDB. Then you create PostgreSQLDAO, OracleDAO and MongoDBDAO, using inheritance for a technical dimension. This, however, mixes up badly with domain inheritance, one would need to combine each of the domain classes with each of the DBMS specific classes (like a PersonPostgreSQLDAO etc. ). Even with two dimensions, this would lead to an explosion of classes, let alone the fact it now becomes unclear whether PersonPostgreSQLDAO should inherit from PersonDAO, from PostgreSQLDAO or just from BaseDAO.

So how do we solve this issue? We can, for example, stick with the domain dimension for the DAOs, model the DBMS hierarchy separately (for example, with a base class DBMS and subclasses PostgreSQLDBMS, OracleDBMS and MongoDBMS), and then let BaseDAO hold a reference to a DBMS instance. A BaseDAO method like findWithAppSql may then delegate any DBMS specific work to the specific DBMS instance. Or, you can do this the other way round: DBMS may have generic methods which work on BaseDAO objects, or each DBMS entry may provide a list of loaded (cached) DAO objects.

So this all boils down to use inheritance for one dimension only per tree. Composition is the right tool when you need a second dimension which should behave orthogonal to the first one. As long as the design sticks to this guideline, implementation inheritance will not cause too much trouble.

Finally, I would like to mention that IMHO a class like BaseDAO (or simply DAO, as I would call it), has semantics. It classifies all subclasses as Data Access Objects of your system, which gives them a clear purpose and distinguishes them from other classes. Maybe you have other classes in mind, where the semantics isn't so clear as here - this, however, may be simply a question of finding a better name for the common base class, or making slight adjustments to those classes.

Addendum: here is an article from 2015 which explains the idea of inheritance and dimensions well: Composition vs. Inheritance: How to Choose?.

September 19, 2025 Score: 2 Rep: 119,848 Quality: Medium Completeness: 80%

Is extending an abstract "base" implementation class an anti-pattern?

Understand that "anti-patterns" are context dependent.

Chopsticks are an anti-pattern, in the context of pizza. Not in the context of ramen.

So what context makes extending an abstract "base" implementation class an anti-pattern? Ownership.

public class MyLoginPageWasNull extends NullPointerException{}

I don't consider this an antipattern because I don't own NullPointerException. This is nice way to give an exception a more descriptive name that works in my domain.

If I did own it, and NullPointerException inherited from something else that I also owned then you'd be right to complain, because this is what causes the yo yo problem.

An ownership boundary creates behavior that can't be moved. That's when I consider dealing with multiple inherited behavior layers an annoying necessity. Doing this to yourself within your own code base is unnecessary pain. Just because you saw people do this with library code doesn't mean that's what you should do with your code. They are dealing with different problems than you are. Stop imitating them.

But, if you are creating a library, and want to be nice to the rest of us, consider this.

October 7, 2025 Score: 1 Rep: 18,658 Quality: Low Completeness: 20%

I don't quite understand your problem but going by the one example you provide you may think of it differently and the following may apply in more cases.

Circle does not have an "is a" relationship with ellipse although it may seem so. Inheritance is to extend, not to restrict. Circle is nothing more than an arbitrary (boolean) property of ellipse. It's an ellipse with two particular properties having the same value.

So whenever you feel something is wrong with inheritence, the alternative may not be encapsulation or composition, your whole understanding of the world may be wrong. It may not be a class you are looking at or for.