Polymorphism and Interfaces in Java

Started by
3 comments, last by dilyan_rusev 9 years, 6 months ago

Hello,

So I recently learned about Interfaces and thought I had a good grasp, but I'm not sure why this example does what it does. It creates an interface object and assign it to an ArrayQueue<T>() object. Why not just write it as an ArrayQueue object to begin with, is there an advantage? I think my question relates more to polymorphism maybe, but I also thought that interfaces aren't objects that are initialized, just implemented from in another class.

Can anyone help clear the air? I would really appreciate any help! huh.png

Advertisement

It creates an interface object and assign it to an ArrayQueue() object.

You've got this backwards. The code creates an object of type ArrayQueue and assigns it to a reference of type QueueInterface. Because ArrayQueue implements the QueueInterface, ArrayQueue "is a" QueueInterface. It is valid for a QueueInterface to point to an ArrayQueue.

Why use an interface? Because sometimes there are objects that can all do the same thing but aren't the same type. For example, consider these classes:

  • ByteStream
  • File
  • Network Socket

All of these objects will let you read() some bytes, so they all have a read() method, but they aren't all the same type of object. So a base class that all these inherit from that contains a read() method doesn't work. But the can all implement a Readable Interface


public interface Readable {
  byte[] read(); // just an example
}

So later you are writing code, and you want to read some data. You could have a method for each type of class, but you don't need to do that. What if someone adds another kind of class that can read() data later? Instead, you use the Readable interface, and any class that lets you read data (of any type) will work.


public class SomeClass {

   public void readData( Readable readable ) { 
      byte[] data = readable.read();
   }
}

I think, therefore I am. I think? - "George Carlin"
My Website: Indie Game Programming

My Twitter: https://twitter.com/indieprogram

My Book: http://amzn.com/1305076532

Glass_Knife is right, you're sound a little confused about how an assignment works, and that's a use of Interfaces.

But, you're right about that particular line being more related to polymorfism than interfaces.

Yes, he could have used ArrayQueue<String> on the left too, but in OOP it's a good practice to keep things general. If you can use an interface or a base class to define a variable you should do it. That way, if you found ArrayQueue is not the best QueueInterface implementation, you only need to change one word in the code. It doesn't sound that great (change one word instead of two), but in bigger projects and complex situations it can make a difference, mainlly in the readability and mantainability of the code.

If you do it with base and derived classes you can get different behaviours if you're not carefull with abstract and overriten methods, but with interfaces you won't have too much troubles.


You've got this backwards. The code creates an object of type ArrayQueue and assigns it to a reference of type QueueInterface. Because ArrayQueue implements the QueueInterface, ArrayQueue "is a" QueueInterface. It is valid for a QueueInterface to point to an ArrayQueue.

Ohhhh, okay. I was def wrong on how the assignment was going on. Makes a lot more sense now!


Yes, he could have used ArrayQueue on the left too, but in OOP it's a good practice to keep things general. If you can use an interface or a base class to define a variable you should do it. That way, if you found ArrayQueue is not the best QueueInterface implementation, you only need to change one word in the code. It doesn't sound that great (change one word instead of two), but in bigger projects and complex situations it can make a difference, mainlly in the readability and mantainability of the code.

I see your point about "general programming", not sure why I skipped that aspect. I guess I was just confused when I thought an interface object was being created, which didnt make sense to me because the methods aren't defined. Totally forgot that myQueue was a reference type and it makes sense for it to refer to a type that extends QueueInterface because it "is-a" type of QueueInterface

Thanks guys! biggrin.png

TL;DR;

The object you create is of type ArrayQueue, because that is what stands right after the new keyword. If ArrayQueue implements QueueInterface, then it declares that every ArrayQueue can be treated exactly as if it were a QueueInterface. This is why you can assign an object of type ArrayQueue to a variable of type QueueInterface. Then on, you use a variable of type QueueInterface to refer to an object that is, in fact, ArrayQueue. Since QueueInterface is an interface, all method calls (myQueue.enqueue("Jim"), etc) on the variable myQueue are actually calls to methods with the same signature in ArrayQueue.

Don't use interfaces for all your variables, this is wrong and evil. Since it is evil, it is done only when it will save your life. Unless you have purpose and a concrete problem to solve, don't use interfaces.

The Long Story

What @DiegoSLTS said is correct, technically.

However, "If you can use an interface or a base class to define a variable you should do it" is correct mostly for certain types of projects, and not in all places.

Scope is important. Methods perform short tasks, and in a short tasks you should be quite certain whether or not to use an ArrayList. Therefore, it doesn't make sense at all to use for a local variable List instead of ArrayList, unless you accept is as a parameter or it comes as a field. The more general a piece of code is, the more difficult it gets to understand.

Using an interface instead of a concrete implementation (class) is only done on purpose - you usually apply design patterns so that other programmers can more easily decipher your intent. A very common mistake is to program in some extensibility (e.g. use interfaces instead of a class) and provide no practical way for your class/module to be extended by clients.

People that teach teach OO in universities are usually scientists, and they publish papers. Code for papers is rarely available even a few years after publication, it is never maintained, and "big" projects for papers are 10,000 lines of code. Also, code is sometimes written by bachelor students or masters, and teams are rarely bigger than 5 people. What is more, researchers are rarely given the chance to analyze or apply their theories on code "in the wild", as companies are keen on keeping their IP.

What I am trying to say is that there is a very big divide between what in theory is good, e.g.

If you can use an interface or a base class to define a variable you should do it. That way, if you found ArrayQueue is not the best QueueInterface implementation, you only need to change one word in the code. It doesn't sound that great (change one word instead of two), but in bigger projects and complex situations it can make a difference, mainlly in the readability and mantainability of the code

and practice. Both researchers and programmers "in the wild" (the jargon they sometimes use for us) agree that complexity is your enemy in software engineering.

What is simple is to be given a task and do it in the simplest possible way. Using interfaces for everything is wrong, because it is needless complexity. We programmers love code that is "good", that we can brag about, and this is why smart hacks and complexity spread like an infectious disease in code. Doing really good code requires you to have the discipline to refrain from adding that fancy design pattern before you need it. This discipline takes a lot of practice.

This topic is closed to new replies.

Advertisement