Java inheritance vs initialization - java

I'm reading J. Bloch's Effective Java and now I'm at inheritance vs composition section. As far as I understood he said that inheritance is not always good.
A related cause of fragility in subclasses is that their superclass
can acquire new methods in subsequent releases. Suppose a program
depends for its security on the fact that all elements inserted into
some collection satisfy some predicate. This can be guaranteed by
subclassing the collection and overriding each method capable of
adding an element to ensure that the predicate is satisfied before
adding the element. This works fine until a new method capable of
inserting an element is added to the superclass in a subsequent
release.
But why doesn't it work? The superclass is just the Collection interface and if we add a new method we just a compile-time error. That's not harmful ever...

Suppose you have a Collection superclass in some library v1.0:
public class MyCollection {
public void add(String s) {
// add to inner array
}
}
You subclass it in order to only accept Strings that have length 5:
public class LimitedLengthCollection extends MyCollection {
#Override
public void add(String s) {
if (s.length() == 5) {
super.add(s);
}
}
}
The contract, the invariant of this class is that it will never contain a String that doesn't have length 5.
Now version 2.0 of the library is released, and you start using it. The base class is modified to:
public class MyCollection {
public void add(String s) {
// add to inner array
}
public void addMany(String[] s) {
// iterate on each element and add it to inner array
}
}
and your subclass is left unmodified. Now users of your subclass can do
LimitedLengthCollection c = new LimitedLengthCollection();
c.addMany(new String[] {"a", "b", "c"});
and the contract of your subclass is thus broken. It was supposed to only accept Strings of length 5, and it doesn't anymore, because an additional method has been added in the superclass.

The problem is not that inheritance could not work.
The problem is that with inheritance the developer can not enforce some behaviour (like the example of the collection that satisfy some predicate) .
When we create a new class rarely it really is a specialized type of another. More often it is something new that use other classes.
So rarely we need inheritance and more often we need to create a class that use other classes to so something.
The IS A vs HAS A
You have to ask yourself:
Class B IS A new sub type of Class A that do the same things of A in different ways ?
or
Class B HAS A class inside to do something different from
what A is intented to do ?
And know that more often the right answer the latter.

if we add a new mehtod we just a compile-time error
That is true only when an abstract method is added to the superclass/interface. If a non-abstract method is added, it is perfectly valid not to override that new method.

Because it (in general) will break the client code that has implemented the Collection class.
In this particular example the security will be broken because malicious users would be able to insert items by using the non yet overridden method that was added after you have shipped your code.
Basing your code on inheriting classes you do not control may bite you in the future.

Related

How do i append a method to a type?

I have a class called CountService. It has this method
public int count()
What I want is to append this function to any java.util.List variable and it will return the size of that list( an integer). I know that list has a size() method. I'm just testing this out if it's possible to append a method to a class. I don't know where it doesn't really belong to.
Sample:
java.util.List<String> list;
list.count();
So even though count does not belong to java.util.List, I want this to be possible in my code. Is there any way?
edit:
It's not specifically for java.util.List only. Rather for any class. Let's say i have Class A and Class B
Now for example Class A represents a String type. And now I have a method in Class B called length(). I want this to be possible.
ClassA_VariableName.length()
And then I'll be able to get the length of object. Class B is like a collection of functions or features that can be appended to any type it was made to be appended to.
The short answer is NO, you cannot do this in Java without using introducing a new type (class or interface) that is declaring the method.
You would have to extend java.util.List
public interface SuperList extends List {
default int count() {
return size();
}
}
And then you would have to introduce a new class that is implementing that interface (and maybe inherit stuff from an existing JDK list e.g. ArrayList).
But if you are not limited to Java you can take a look at other JVM languages. For example Groovy or Kotlin provide features to add a method to a class.
Here is an example in Groovy that uses the Expando class to add a method to a list.
List list = new ArrayList()
list.metaClass.count() {
delegate.size()
}
// now call it
list.count()
In Java you can not to add methods to classes which sources you can not change unlike javascript or ruby.
You can create your own class and inherit it from say ArrayList:
class MyList extends ArrayList {
public int count() {
//...
}
}

What's the harm in using Anonymous class?

The question arose while reading a answer to this question - How do I join two lists in java. This answer gave the solution
List<String> newList = new ArrayList<String>() { { addAll(listOne); addAll(listTwo); } };
Reading the comments, users said it was evil and ugly and should not be used in production.
I would like to know what's the harm in using this? Why is it ugly, evil or bad to use in production?
Except for the already mentioned issues regarding good programming style and inheritance misuse, there is one more subtle problem - inner classes and (non-static) anonymous class instances act as closures. This means that they keep an implicit reference to the enclosing class instance. This can result in preventing of garbage collection and in the end, a memory leak.
Given an example piece of source code:
public interface Inner {
void innerAction();
}
public class Outer {
public void methodInOuter() {}
private Inner inner = new Inner() {
public void innerAction() {
// calling a method outside of scope of this anonymous class
methodInOuter();
}
}
}
What happens at compilation time, is that the compiler creates a class file for the new anonymous subclass of Inner which gets a so-called synthetic field with the reference to the instance of the Outer class. The generated bytecode will be roughly equivalent to something like this:
public class Outer$1 implements Inner {
private final Outer outer; // synthetic reference to enclosing instance
public Outer$1(Outer outer) {
this.outer = outer;
}
public void innerAction() {
// the method outside of scope is called through the reference to Outer
outer.methodInOuter();
}
}
Such capture of reference to the enclosing instance happens even for anonymous classes that never actually access any of methods or fields of the enclosing class, such as the double-brace initialized (DBI) list in your question.
This results in the fact that the DBI list keeps a reference to the enclosing instance as long as it exists, preventing the enclosing instance from being garbage collected. Suppose the DBI list happens to live for a long time in the application, for example as a part of the model in MVC pattern, and the captured enclosing class is for example a JFrame, which is quite a large class with lots of fields. If you created a couple of DBI lists, you would get a memory leak very quickly.
One possible solution would be using DBI only in static methods, because there is no such enclosing instance available in their scope.
On the other hand, I would still argue that using DBI is still not necessary in most cases. As for the list joining, I would create a simple reusable method, which is not only safer, but also more concise and clear.
public static <T> List<T> join(List<? extends T> first, List<? extends T> second) {
List<T> joined = new ArrayList<>();
joined.addAll(first);
joined.addAll(second);
return joined;
}
And then the client code becomes simply:
List<String> newList = join(listOne, listTwo);
Further reading:
https://stackoverflow.com/a/924536/1064809
The "ugly" and "do not use in production" comments refer to this specific use of anonymous classes, not to anonymous classes in general.
This specific use assigns newList an anonymous subclass of ArrayList<String>, an entirely new class created with a single purpose in mind - namely, initializing a list with the content of two specific lists. This is not very readable (even an experienced reader would spend a few seconds figuring it out), but more importantly, it can be achieved without subclassing in the same number of operations.
Essentially, the solution pays for a small convenience with creating a new subclass, which may result in problems down the road, for example, in situations when you try to persist this collection using an automated framework that expects collections to have specific types.
This particular use of anonymous classes has several problems:
it's a little-known idiom. Developers that don't know it (or know it an don't use it a lot) will be slowed down when reading and/or modifying code that uses it.
it's actually misusing a language feature: you're not trying to define a new kind of ArrayList, you just want some array list with some existing values in it
it creates a new class that takes up resources: disk space to hold the class definition, time to parse/verify/... it, permgen to hold the class definition, ...
even if the "real code" is slightly longer, it can easily be moved into an aptly-named utility method (joinLists(listOne, listTwo))
In my opinion #1 is the most important reason to avoid it, closely followed by #2. #3 is usually not that much of a problem, but should not be forgotten.
Because you don't need a separate subclass - you just need to create a new ArrayList of the normal class, and addAll() both lists into it.
Like so:
public static List<String> addLists (List<String> a, List<String> b) {
List<String> results = new ArrayList<String>();
results.addAll( a);
results.addAll( b);
return results;
}
It's evil to create a subclass, that isn't needed. You don't need to extend or subclass behaviour - just change data values.
It's not a bad approach per se, say, in performance or anything like that, but the approach is a bit obscure and when using something like this, you always (say, 99%) have to explain this approach. I think that's one of the biggest reasons not to use this approach, and while typing:
List<String> newList = new ArrayList<String>();
newList.addAll(listOne);
newList.addAll(listTwo);
is a little more typing, it's a bit easier to read, which helps a lot in understanding or debugging code.
In your example it really looks evil and ugly, at least to me - it's difficult to understand what's going on in the code. But there are some patterns of using anonymous classes that people are used to because they see them very often, eg
Arrays.sort(args, new Comparator<String>() {
public int compare(String o1, String o2) {
return ...
}});
I would call the above a best practice case.

composition-and-forwarding approach for a class with two Lists

I have read Item 16 from Effective Java and
Prefer composition over inheritance? and now try to apply it to the code written 1 year ago, when I have started getting to know Java.
I am trying to model an animal, which can have traits, i.e. Swimming, Carnivorous, etc. and get different type of food.
public class Animal {
private final List<Trait> traits = new ArrayList<Trait>();
private final List<Food> eatenFood = new ArrayList<Food>();
}
In Item 16 composition-and-forwarding reuseable approach is suggested:
public class ForwardingSet<E> implements Set<E> {
private final Set<E> s;
public ForwardingSet(Set<E> s) {this.s = s;}
//implement all interface methods
public void clear() {s.clear();}
//and so on
}
public class InstrumentedSet<E> extends ForwardingSet<E> {
//counter for how many elements have been added since set was created
}
I can implement ForwardingList<E> but I am not sure on how I would apply it twice for Animal class. Now in Animal I have many methods like below for traits and also for eatenFood. This seems akward to me.
public boolean addTrait (Trait trait) {
return traits.add(trait);
}
public boolean removeTrait (Trait trait) {
return traits.remove(trait);
}
How would you redesign the Animal class?
Should I keep it as it is or try to apply ForwardingList?
There is no reason you'd want to specialize a List for this problem. You are already using Composition here, and it's pretty much what I would expect from the class.
Composition is basically creating a class which has one (or usually more) members. Forwarding is effectively having your methods simply make a call to one of the objects it holds, to handle it. This is exactly what you're already doing.
Anyhow, the methods you mention are exactly the sort of methods I would expect for a class that has-a Trait. I would expect similar addFood / removeFood sorts of methods for the food. If they're wrong, they're the exact sort of wrong that pretty much everyone does.
IIRC (my copy of Effective Java is at work): ForwardingSet's existence was simply because you cannot safely extend a class that wasn't explicitly designed to be extended. If self-usage patterns etc. aren't documented, you can't reasonably delegate calls to super methods because you don't know that addAll may or may not call add repeatedly for the default implemntation. You can, however, safely delegate calls because the object you are delegating to will never make a call the wrapper object. This absolutely doesn't apply here; you're already delegating calls to the list.

Java interfaces and types

Let's say you have some Java code as follows:
public class Base{
public void m(int x){
// code
}
}
and then a subclass Derived, which extends Base as follows:
public class Derived extends Base{
public void m(int x){ //this is overriding
// code
}
public void m(double x){ //this is overloading
// code
}
}
and then you have some declarations as follows:
Base b = new Base();
Base d = new Derived();
Derived e = new Derived();
b.m(5); //works
d.m(6); //works
d.m(7.0); //does not compile
e.m(8.0); //works
For the one that does not compile, I understand that you are passing in a double into Base's version of the m method, but what I do not understand is... what is the point of ever having a declaration like "Base b = new Derived();" ?
It seems like a good way to run into all kinds of casting problems, and if you want to use a Derived object, why not just go for a declaration like for "e"?
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java. The way I learned it earlier this summer was, every object has one class, which corresponds to the name of the class following "new" when you instantiate an object, but an object can have as many types as it wants. For example, "e" has type Base, Derived, (and Object ;) ) but its class is Derived. Is this correct?
Also, if Derived implemented an interface called CanDoMath (while still extending Base), is it correct to say that it has type "CanDoMath" as well as Base, Derived, and Object?
I often write functions in the following form:
public Collection<MyObject> foo() {}
public void bar(Collection<MyObject> stuff){}
I could just as easily have made it ArrayList in both instances, however what happens if I later decide to make the representation a Set? The answer is I have a lot of refactoring to do since I changed my method contract. However, if I leave it as Collection I can seamlessly change from ArrayList to HashSet at will. Using the example of ArrayList it has the following types:
Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
There are a number of cases where confining yourself to a particular (sub)class is not desired, such as the case you have where e.m(8.0);. Suppose, for example, you have a method called move that moves an object in the coordinate graph of a program. However, at the time you write the method you may have both cartesian and radial graphs, handled by different classes.
If you rely on knowing what the sub-class is, you force yourself into a position wherein higher levels of code must know about lower levels of code, when really they just want to rely on the fact that a particular method with a particular signature exists. There are lots of good examples:
Wanting to apply a query to a database while being agnostic to how the connection is made.
Wanting to authenticate a user, without having to know ahead of time the strategy being used.
Wanting to encrypt information, without needing to rip out a bunch of code when a better encryption technique comes along.
In these situations, you simply want to ensure the object has a particular type, which guarantees that particular method signatures are available. In this way your example is contrived; you're asking why not just use a class that has a method wherein a double is the signature's parameter, instead of a class where that isn't available. (Simply put; you can't use a class that doesn't have the available method.)
There is another reason as well. Consider:
class Base {
public void Blah() {
//code
}
}
class Extended extends Base {
private int SuperSensitiveVariable;
public setSuperSensistiveVariable(int value) {
this.SuperSensistiveVariable = value;
}
public void Blah() {
//code
}
}
//elsewhere
Base b = new Extended();
Extended e = new Extended();
Note that in the b case, I do not have access to the method set() and thus can't muck up the super sensitive variable accidentally. I can only do that in the e case. This helps make sure those things are only done in the right place.
Your definition of type is good, as is your understanding of what types a particular object would have.
What is the point of having Base b = new Derived();?
The point of this is using polymorphism to change your implementation. For example, someone might do:
List<String> strings = new LinkedList<String>();
If they do some profiling and find that the most common operation on this list is inefficient for the type of list, they can swap it out for an ArrayList. In this way you get flexibility.
if you want to use a Derived object
If you need the methods on the derived object, then you would use the derived object. Have a look at the BufferedInputStream class - you use this not because of its internal implementation but because it wraps an InputStream and provides convenience methods.
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java.
It sounds like your teacher is referring to Interfaces and Classes as "types". This is a reasonable abstraction, as a class that implement an interface and extends a class can be referred to in 3 ways, i.e.
public class Foo extends AbstractFoo implements Comparable<Foo>
// Usage
Comparable<Foo> comparable = new Foo();
AbstractFoo abstractFoo = new Foo();
Foo foo = new Foo();
An example of the types being used in different contexts:
new ArrayList<Comparable>().Add(new Foo()); // Foo can be in a collection of Comparable
new ArrayList<AbstractFoo>().Add(new Foo()); // Also in an AbstractFoo collection
This is one of the classic problems on object oriented designs. When something like this happens, it usually means the design can be improved; there is almost always a somewhat elegant solution to these problems....
For example, why dont you pull the m that takes a double up into the base class?
With respect to your second question, an object can have more than one type, because Interfaces are also types, and classes can implement more than one interface.

Why would you declare an Interface and then instantiate an object with it in Java?

A friend and I are studying Java. We were looking at interfaces today and we got into a bit of an discussion about how interfaces are used.
The example code my friend showed me contained this:
IVehicle modeOfTransport1 = new Car();
IVehicle modeOfTransport2 = new Bike();
Where IVehicle is an interface that's implemented in both the car and bike classes.
When defining a method that accepts IVehicle as a parameter you can use the interface methods, and when you run the code the above objects work as normal. However, this works perfectly fine when declaring the car and bike as you normally would like this:
Car modeOfTransport1 = new Car();
Bike modeOfTransport2 = new Bike();
So, my question is - why would you use the former method over the latter when declaring and instantiating the modeOfTransport objects? Does it matter?
There is a big plus on declaring them using the interface, which is what is known as "coding to an interface" instead of "coding to an implementation" which is a big Object Oriented Design (OOD) principle, this way you can declare a method like this:
public void (IVehicle myVehicle)
and this will accept any object that implements that interface, then at runtime it will call the implementation like this:
public void (IVehicle myVehicle)
{
myVehicle.run() //This calls the implementation for that particular vehicle.
}
To answer the original question, why would you use one over the other there are several reasons:
1) Declaring them using an interface, means you can later substitute that value with any other concrete class that implements that interface, instead of being locked into that particular concrete class
2) You can take full advantage of polymorphism by declaring them using an interface, because each implementation can call the correct method at runtime.
3) You follow the OOD principle of code to an interface
It doesn't matter there.
Where it really matters is in other interfaces that need to operate on IVehicle. If they accept parameters and return values as IVehicle, then the code will be more easily extendible.
As you noted, either of these objects can be passed to a method that accepts IVehicle as a parameter.
If you had subsequent code that used Car or Bike specific operations that were used, then it would be advantageous to declare them as Car or Bike. The Car and Bike specific operations would be available for each of the relevant objects, and both would be usable (i.e. could be passed) as IVehicle.
You're really asking: what reference type should I use?
Generally you want to use as general a reference type as possible that still gives you access to the behavior that you need. This means any of the interfaces or parent classes of your concrete type, rather than the concrete type itself. Of course, don't take this point too far -- for example, you certainly don't want to declare everything as an Object!
Consider these options:
Set<String> values1 = new TreeSet<String>();
TreeSet<String> values2 = new TreeSet<String>();
SortedSet<String> values3 = new TreeSet<String>();
All three are valid, but generally the first option of values1 is better because you will only be able to access the behavior of the Set interface, so later you can swap in another implementation quite easily:
Set<String> values1 = new HashSet<String>();
Beware of using the second option values2. It allows you to use specific behavior of the TreeSet implementation in such a way that swapping in a different implementation of Set becomes more difficult. This is fine as long as that's your goal. So, in your example, use a Car or Bike reference only when you need access to something that's not in the IVehicle interface. Be aware though that the following would not work:
TreeSet<String> values2 = new HashSet<String>(); // does not compile!
Still there are times when you need access to the methods that are not in the most general type. This is illustrated in the third option values3 -- the reference is more specific than Set, which allows you to rely on the behavior of SortedSet later.
TreeSet<String> values3 = new ConcurrentSkipListSet<String>();
The question about reference types applies not only where variables are declared, but also in methods where you have to specify the type of each parameter. Fortunately the "use as general a reference type as possible" rule of thumb applies to method parameters, too.
Program to an interface rather than an implementation.
When you program to an interface you will write code that can handle any kind of Vehicle. So in the future your code, without modification, should work with Trains and Planes.
If you ignore the interface then you are stuck with CArs and Bikes, and any new Vehicles will require additional code modifications.
The principle behind this is:
Open to Extension, Closed to Modification.
Because you don't really care what the implementation is... only what it's behavior is.
Say you have an animal
interface Animal {
String speak();
}
class Cat implements Animal {
void claw(Furniture f) { /* code here */ }
public String speak() { return "Meow!" }
}
class Dog implements Animal {
void water(FireHydrant fh) { /* code here */ }
public String speak() { return "Woof!"; }
}
Now you want to give your kid a pet.
Animal pet = new ...?
kid.give(pet);
And you get it back later
Animal pet = kid.getAnimal();
You wouldn't want to go
pet.claw(favorateChair);
Because you don't know if the kid had a dog or not. And you don't care. You only know that --Animals-- are allowed to speak. You know nothing about their interactions with furniture or fire hydrants. You know animals are for speaking. And it makes your daughter giggle (or not!)
kid.react(pet.speak());
With this, when you make a goldfish, the kid's reaction is pretty lame (turns out goldfishes don't speak!) But when you put in a bear, the reaction is pretty scary!
And you couldn't do this if you said
Cat cat = new Cat();
because you're limiting yourself to the abilities of a Cat.
Honestly your argument is rather moot. What's happening here is an implicit conversion to an IVehicle. You and your friend seem to be arguing about whether it's better to do it immediately (as per the first code listing), or later on (when you call the method, as per the second code listing). Either way, it's going to be implicitly converted to an IVehicle, so the real question is -- do you need to deal with a Car, or just a Vehicle? If all you need is an IVehicle, the first way is perfectly fine (and preferable if at a later point you want to transparently swap out a car for a bike). If you need to treat it like a car at other points in your code, then just leave it as a car.
Declaring interfaces and instantiating them with objects allows for a powerful concept called polymorphism.
List<IVehicle> list = new ArrayList<IVehicle>();
list.add(new Car());
list.add(new Bike());
for (int i = 0; i < list.size(); ++i)
list.get(i).doSomeVehicleAction(); // declared in IVehicle and implemented differently in Car and Bike
To explicitly answer the question: You would use an interface declaration (even when you know the concrete type) so that you can pass multiple types (that implement the same interface) to a method or collection; then the behavior common to each implementing type can be invoked no matter what the actual type is.
well interfaces are behaviors and classes are their implementation so there will be several occasions later when you will program where you will only know the behaviors(interface). and to make use of it you will implement them to get benefit out of it. it is basically used to hiding implementation details from user by only telling them the behavior(interface).
Your intuition is correct; the type of a variable should be as specific as possible.
This is unlike method return types and parameter types; there API designers want to be a little abstract so the API can be more flexible.
Variables are not part of APIs. They are implementation details. Abstraction usually doesn't apply.
Even in 2022, it's confusing to understand the true purpose of an interface even to a trained eye who didn't start his/her career in java.
After reading a lot of answers in various online posts, I think that an interface is just a way to not care about the implementation details of a certain activity which is being passed down to a common goal (a certain method). To make it easy, a method doesn't really care how you implement your operations but only cares about what you pass down to it.
The OP is correct in a way to ask why we couldn't just reference to the type of the concrete class than to use an interface. But, we cannot think or understand the use case of an interface in a isolated pov.
Most explanation won't justify it's use unless you look at how classes like ArrayList and LinkedList are derived. Here is my simple explanation.
Class CustomerDelivery {
line 2 -> public void deliverMeMyIphone( DeliveryRoutes x //I don't care how you deliver it){
//Just deliver to my home address.
}
line 3 -> DeliveryRoutes a = new AmazonDelivery();
DeliveryRoutes b = new EbayDelivery();
//sending IPhone using Amazon Delivery. Final act.
deliverMeMyIphone(a.route());
//sending IPhone using eBay Delivery. Final act
deliverMeMyIphone(b.route());
}
Interface DeliveryRoutes {
void route(); // I dont care what route you take, and also the method which takes me as an argument won't care and that's the contract.
}
Class AmazonDelivery implements DeliveryRoutes {
#overide route() {
// Amazon guy takes a different route
}
}
Class EbayDelivery implements DeliveryRoutes {
#overide route() {
// ebay guy takes a different route
}
}
From the above example In line 2, just imagine to yourself what would happen if you cast the type of value x to a concrete class like AmazonDelivery and not the interface DeliveryRoutes type? or what would happen in line 3 if you change the type from the interface to AmazonDelivery type? It would be a mess. Why? because the method deliverMeMyIphone will be forced to work with only one type of delivery i.e AmazonDelivery and won't accept anything else.
Most answers confuse us with by saying Interfaces helps in multiple inheritance which is true, don't get me wrong, but it's not the only story.
With "IVehicle modeOfTransport1 = new Car();", methods owned only by Car are not accessible to modeOfTransport1. I don't know the reason anyway.

Categories