Reputation: 7585
Let's say I have a CSV file and I create a class called CsvFile
which extends from java.io.File
. This class can parse a CSV file and return some data like how many columns are in the file. It can also be used for functions which takes java.io.File
as input. Like FileUtils.copyFile(File from, File to)
.
My colleague thinks I expose too much from inheritance. His idea is to wrap java.io.File
by holding it in a private property, instead of inheriting it. He think exposing all public method/property from file breaks encapsulation, but I take it as a benefit since we get all functions in java.io.File
for free.
What do you think?
Upvotes: 13
Views: 2392
Reputation: 561
As to your question
Will inheritance break encapsulation?
Then, according to Joshua Bloch's Effective Java, inheritance always breaks encapsulation:
Unlike method invocation, inheritance violates encapsulation [Snyder86]. In other words, a subclass depends on the implementation details of its superclass for its proper function.
Regarding whether you should use inheritance or composition, as many people already said, it depends on if your CsvFile
is-a file, in the sense of java.util.File
.
Upvotes: 0
Reputation: 62155
The approach your colleague mentions also has the benefit that your API becomes very small by only exposing methods you really need - which makes it clear how to the user how to use your class (you can think of your public API as some sort of documentation).
Upvotes: 0
Reputation: 10472
This is actually a great debate. Your colleague is on the right side of history on this one. In general the question of inheritance comes down to the relationships of is-a vs. has-a. In general it is more flexible to use composition than inheritance. In your case its a close call. After all a csv file isa file. saying csvfile has-a file does not even sound right. What might be considered as well is to do the inheritance but than wrap the inherited file so that only those CSV file methods that you want are exposed. I would also look into some design patterns around this where you want to inherit from A but expose a more limited interface to the world. I am almost sure there is a design pattern for this. just can't remember the name ....
"Either or I think not, but combining both is the way. First inheritance so that the wheel is not reinvented, than to patterns that encapsulate so that the wheel serves its purpose."
Upvotes: 1
Reputation: 3903
Maybe my point of view is too liberal but... Encapsulation and inheritance are there for a reason. (Watch the 'evolution' from assemblers to high level languages.) That reason is the programmer. With higher level abstractions/paradigms you can write better code. The trick is to define 'better' of course. For me this is maintainability, self documentation and code reuse. That's why I would choose the encapsulation over inheritance in your particular case. Maybe it's a bit more work to write it once, but sooooo much easier to maintain in the future. (Assuming this CSV stuff is part of a bigger project of course.)
Upvotes: 0
Reputation: 624
You might also consider making it more generic so it can accept a CSV-formatted InputStream or Reader from a wide variety of sources that cannot (or cannot easily) emit to the filesystem. You can still have a java.io.File setter/constructor for convenience.
Upvotes: 1
Reputation: 65
I think it all depends of the purpose of the class. If you are truly trying to extend the behavior then I would say it makes sense. If you are not extending behavior of File but are just making a CSV object then encapsulation would limit its behaviors to only what it intention is.
Upvotes: 5
Reputation: 726489
I would rather agree with your colleague: inheriting java.util.File
would expose methods that are not applicable to CsvFile
objects, such as list()
, listFiles()
, setExecutable()
, and so on.
Making java.util.File
a property behind a getter sounds like a better choice: it does not reveal irrelevant operations to the users of your class, and lets you inherit from a base class of your choice.
Upvotes: 15