This question already has answers here:
What does it mean to "program to an interface"?
(33 answers)
Closed 3 years ago.
I'm just getting started with interfaces and I cannot grasp the concept.
class Client {
IServer x = new Server();
void m() {
x.p();
}
}
interface IServer {
void n();
void p();
}
class Server implements IServer{
public void n() {
System.out.println("Methode n");
}
public void p() {
System.out.println("Methode p");
}
}
So client should be able to use the methods provided by server through the interface IServer.
Is IServer x = new server(); correct? The examples that I found (https://www.w3schools.com/java/java_interface.asp) all build interfaces and then the main class calls the other class without using the interface.
Thank you for your help, I guess I'm just missing something obvious here...
A good explanation of how interfaces work and why they're used can be done with the following example. Let's say we have a zoo object with animals. We want all the animals to be able to make a noise depending on what animal they are. We start with the following class:
public class Zoo {
private List<Animal> animals;
public Zoo() {
animals = new ArrayList<>();
}
public void addAnimal(Animal animal) {
animals.add(animal);
}
public void roar() {
for(Animal a : animals) {
a.makeNoise();
}
}
}
This is basically just an object containing a list of animals and we can add animals to this list. When we call the method roar we want all the animals to make their own noise and print it to the console. Now this is where interfaces are useful, since we know we will have multiple types of animals we can specify what a basic "animal" can do, these are generic traits that describe that they can do something but not how. For instance, a box and a human can both move, but a human can move on its own and a box cannot. Or maybe a human can move up stairs but a dog cannot. Knowing this, we create a basic interface describing that an animal can make a noise:
public interface Animal {
void makeNoise();
}
This will allow us to create as many animals as we want, while forcing them to implement our defined functionalities. So now, we can create some animals:
public class Cat implements Animal {
private String name;
public Cat(String name) {
this.name = name;
}
#Override
public void makeNoise() {
System.out.println(name + "said Meow");
}
}
public class Dog implements Animal {
#Override
public void makeNoise() {
System.out.println("Woof");
}
}
As you can see, we can give both classes their own functionality, while still enforcing both classes to at least be able to make their respective noise. In this case a cat can have a name, while a dog cannot. This means that we can now fill our Zoo with any animal we want, and since they all have the same overlaying interface we don't have to, for instance, create more than one Collection to store each type of animal. We can just throw them all on one big pile based on their interface and we can call the proper method through the interface:
public void run() {
Zoo zoo = new Zoo();
zoo.addAnimal(new Cat("Bob"));
zoo.addAnimal(new Dog());
zoo.addAnimal(new Cat("William"));
zoo.roar();
}
As far as types are concerned. It works like it does in real life. Following our example, a dog is an Animal, but an animal is not necessarily a dog. Since our code in this case (when it's inside the zoo) only knows that it has Animals, but not what specific types, it only allows us access to the functionalities defined in the interface.
This means that, we are allowed to do stuff like:
Animal a = new Dog();
Dog b = new Dog();
Animal c = new Cat("Bob");
Cat d = new Cat("Wilbert");
But not:
Animal a = new Dog();
Dog b = a;
Since, as soon as we assign a and say "you're of type animal" it doesn't know if the data inside a is actually a dog or not.
A better documentation is the official at https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html
There are a number of situations in software engineering when it is important for disparate groups of programmers to agree to a "contract" that spells out how their software interacts. Each group should be able to write their code without any knowledge of how the other group's code is written. Generally speaking, interfaces are such contracts.
With an Interface, you can enforce a Class to have a particular behavior, defined inside the Interface, BUT implemented inside the class that implement that Interface.
And also, if you know that an object Dog implements the Interface Run and that Interface declare the method run() {}, you can safely invoke the method run on the object Dog, because it contains the method implementation:
Interface Run
{
public void run();
}
class Dog implements Run
{
public void run()
{
// the dog is running
}
}
Dog dog = new Dog();
dog.run();
Related
Why would you declare the "thing" object as the super-class when you can use the subclass, which would give you access to all of the same methods and fields and wouldn't require type casting for methods in the B class.
public class A{}
public class B extends A{}
public class main()
{
A thing = new B();
}
This is called Polymorphism. If you had another class called C extends A you could create a List<A> and put both B and C there. Then you could iterate over them and call the common method etc.
Maybe because you want to feed() several Animals at same time, without caring about the real type of Animal:
interface Animal { void feed();}
class Dog implements Animal { public void feed() { /* feed a dog (give it a cat) */ }}
class Cat implements Animal { public void feed() { /* feed a cat (give it a bird) */ }}
class Cow implements Animal { public void feed() { /* feed a cow (give it some grass) */ }}
// Now I have some animals mixed somewhere (note that I am allowed to have the array declaring a supertype (Animal), and it can contain many kind of different animals)
Animal[] manyAnimals = new Animal[]{ new Dog(), new Cat(), new Cow() };
// I can feed them all without knowing really what kind of Animal they are. I just know they are all Animal, and they will all provide a feed() method.
for(Animal some : manyAnimals) { some.feed(); }
It is polymorphism.
This example might help you understand it.
In a company there are both Permanent and Contract employees are there. The salary calculations happen differently for different type of employee. But PF calculation is common for both type of employees. So in this case you can write common code in super class(Employee) and only custom code in sub class(PermanentEmployee and ContractEmployee). This way you can make code reusable instead of writing again and again and also you can achieve dynamic polymorphism. Most of the time the type of employee is decided at run time.
I want to understand the use-case of setting a parent reference to a child object.
Example: Dog class extends Animal class. (No interfaces, mind it)
I would normally create an object of Dog like this:
Dog obj = new Dog();
Now, since Dog is a subclass of Animal it already has access to all of Animal's methods and variables. Then, what difference does this make:
Animal obj = new Dog();
Please provide a proper use-case with an code snippet of its use. No theoretical articles about 'Polymorphism' or 'Coding to interfaces' please!
Code:
public class Polymorphism {
public static void main(String[] args){
Animal obj1 = new Dog();
Dog obj2 = new Dog();
obj1.shout(); //output is bark..
obj2.shout(); //output is bark..
}
}
class Animal{
public void shout(){
System.out.println("Parent animal's shout");
}
}
class Dog extends Animal{
public void shout(){
System.out.println("bark..");
}
}
class Lion extends Animal{
public void shout(){
System.out.println("roar..");
}
}
class Horse extends Animal{
public void shout(){
System.out.println("neigh");
}
}
Output is the same for both the cases. Then why do we set parent reference to child object?
Let me code some time.
List<String> list = new ArrayList<String>;
list.doThis();
list.doThat();
Oh wait ..I'm gone mad. I want to use LinkedList instead of ArrayList
List<String> list = new LinkedList<String>;
list.doThis();
list.doThat();
Yup, I have to change only declaration part. No need to touch all of my code. Thanks to programming to interfaces and with super classes.
This is an implementation of a principle which says -
Program to an interface, not to an implementation.
As an example, if you design a method to accept a reference of type Animal, then in future you can easily pass an= Cat implementation to it (provided of course that the Cat is a sub-type of Animal.
Which means -
public void doSomethingWithAnimal(Animal animal) {
// perform some action with/on animal
}
is much more flexible than -
public void doSomethingWithAnimal(Dog d) {
// your code
}
because for the first method, you can easily do something like -
doSomethingWithAnimal(new Cat());
if you ever decide to create new Cat type, inheriting from Animal.
Think generally, you will know java casting/oop concept.
Dog is a type of Animal so you can assign it to an animal.
But you can't assign Animal to a Dog. Because it can be any other animal like Cat. If you are sure the object is Dog, you can caste that to Animal. If the Animal is of type Dog then you cannot magically cast to a Goat.
Although there are some good answers (among the "meh" ones), it seems like none was acceptable for you. Maybe they are too theoretical or contain details that you are not interested in. So another try:
For the example that you described, it does not matter. If you really only have a two-line method like
void doit()
{
Animal x = new Dog();
x.shout();
}
then you could also have written
void doit()
{
Dog x = new Dog();
x.shout();
}
and this would not have a direct disadvantage.
One could even generalize this statement: For a reference that is only used locally, it does not matter. When you declare the reference in the method, and only use this reference in this method, and do not pass it to other methods, then there is no direct advantage in declaring it as Animal instead of as Dog. You can to both.
But...
even if you are not interested in this, I can't omit it:
... using the parent type is part of a best practice:
You should always use the least specific type that is sufficient for what you want to do
This has various technical reasons, regarding abstraction, generalization, flexibility, the application of polymorphism, and one could even go so far to call it a sort of "type hygiene".
And this explicitly also refers to the case where the reference is only used locally: If you don't want to call methods that are specific for the type Dog, but only want to call methods from the Animal class, then you should make this clear by declaring the variable as an Animal - simply because that's the least specific type that you need. So there is an indirect advantage of using the type Animal in these cases - namely that it is clear that the following code will only use methods of the Animal class, and none of the Dog class.
One could continue and go very far with further justifications, use case examples and technical details here. But for this, you may refer to the other answers, or some intermediate or advanced texbooks and tutorials.
Okay. I think I got my answer.
public class Polymorphism {
public static void main(String[] args){
Animal obj1 = new Horse();
Horse obj2 = new Horse();
obj1.shout(); //output is neigh..
obj2.shout(); //output is neigh..
obj1.winRaces(); /*But this is not allowed and throws compile time error,
even though the object is of Animal type.*/
}
}
class Animal{
public void shout(){
System.out.println("Parent animal's shout");
}
}
class Horse extends Animal{
public void shout(){
System.out.println("neigh..");
}
public void winRaces(){
System.out.println("won race..");
}
}
So, when we use parent reference for child class object, we cannot access any specific methods in child class (that are not present in parent class) using that object.
This would be when you want the code that you're writing to work against the Animal interface instead of the Dog implementation. Creating an object in this way makes your code more robust in the long term.
I frequently use:
List<Object> aList = new ArrayList<>();
This is important when defining class level variables, because you want your whole object to work even if you change an unimportant detail later.
When you start with such a simple example, you can't see any benefits because you have tightly coupled the variable to the actual type of object it will hold.
Polymorphism comes into its own only when you consider method declarations where the parameter is of the least specific type needed by the method's implementation: then you can call it with any subtype and the method will know what to do with it, even though it has no knowledge of the actual object type. That's the essence of Liskov substitutability of types.
So imagine you have a method
int getAge(Animal a) {
return Days.toYears(currentDate() - a.dateOfBirth());
}
The method will work against any Animal, even those you defined after defining the method.
But, if you happen to understand the above, yet ask specifically why one would write
Animal a = new Dog();
then it still often makes sense: you promise up-front that you won't refer to any dog-specific aspects of the instance. Typically you'll see
List<String> strings = new ArrayList<>();
and in this case we know that the rest of the code doesn't rely on the specific choice of ArrayList as list implementation. This is a much smaller difference than the one decribed above, but it's a combination of brevity, safety, and custom which makes it stick.
Looking at the question:-
Polymorphism in java: Why do we set parent reference to child object?
In a method like below(Factory Pattern):-
public Animal doSomething(String str){
if(str.equals("dog")){
return new Dog();
}
else if(str.equals("cat")){
return new Cat();
}
else {
return new Animal();
}
}
You get a type of Animal and actual object of either Dog or Cat so calling a method of Animal will call the method overridden in actual Object of either Dog or Cat if the called method is overridden in base class. It provides you with the flexibility at run time to decide which method to run depending on the actual object and overridden method in base class if any.
The complete example is as under :-
package com.test.factory;
public class Animal{
public void shout(){
System.out.println("Parent animal's shout");
}
}
package com.test.factory;
public class Dog extends Animal{
#Override
public void shout(){
System.out.println("bark..");
}
}
package com.test.factory;
public class Horse extends Animal{
#Override
public void shout(){
System.out.println("neigh");
}
}
package com.test.factory;
public class Lion extends Animal{
#Override
public void shout(){
System.out.println("roar..");
}
}
package com.test.factory;
public class AnimalFactory {
public Animal createAnimal(String str){
if(str.equals("dog")){
return new Dog();
}
else if (str.equals("horse")){
return new Horse();
}
else if(str.equals("lion")){
return new Lion();
}
else{
return new Animal();
}
}
}
package com.test.factory;
package com.test.factory;
public class Polymorphism {
public static void main(String[] args){
AnimalFactory factory = new AnimalFactory();
Animal animal = factory.createAnimal("dog");
animal.shout();
animal = factory.createAnimal("lion");
animal.shout();
animal = factory.createAnimal("horse");
animal.shout();
animal = factory.createAnimal("Animal");
animal.shout();
}
}
Output is :-
bark..
roar..
neigh
Parent animal's shout
The AnimalFactory has a createAnimal method which returns Animal. Since Dog, Lion and Horse are all animals. So we are able to create Dog, Lion and Horse objects by using Animal return type. What we achieved using Animal return type is
Animal animal = new Dog();
Animal animal = new Lion();
Animal animal = new Horse();
which is not possible without the Animal return type.
If I use return type as Dog in createAnimal method then it cannot return Lion or Horse and like wise.
In the book, they are trying to create their own arrayList Class using an array object, using polymorphism.
I understand what the code is doing but it will not allow it to compile because their is no dog or cat class.
I have each of them in seperate files.
error: animal cannot be resolved to a type
public class MyAnimalList {
private Animal[] animals = new Animal[5];
private int nextIndex = 0;
public void add(Animal a ) {
if (nextIndex < animals.length) {
animals[nextIndex] = a;
System.out.println("Animal added at " + nextIndex);
nextIndex++;
}
}
}
//next snippet
public class AnimalTestDrive{
public static void main (String[]args) {
MyAnimalList list = new MyAnimalList():
Dog a = new Dog();
Cat c = new Cat();
list.add(a);
list.add(c);
}
}
Okay so the whole concept of Polymorphism is Objects can be categorized into more generic objects.
For example: Dogs are Animals, Cats are Animals, and Animals are Living Things
So Polymorphism allows you to define a bunch of generic characteristics(i.e. fields and methods) for one class(Animal) so that all other classes that are categorized under that class(Cats, Dogs, ect) can extend those characteristics.
Now the reason your code is not working is because you have not defined the class Dog or Cat in order to do that you need to first create a class animal that has certain attributes as such:
public class Animal{
//some fields
//constructor
//methods
}
and then create two other classes Dog and Cat that extend that (extend is a key word meaning that this object is in the category of)
so you would then create:
public class Dog extends Animal{
//some fields
//constructor
//methods
}
public class Cat extends Animal{
//some fields
//constructor
//methods
}
Do you a modern IDE (e.g. eclipse) ? or are you doing it from command line ?
** If you are NOT using an IDE, I strongly suggest you to do so at the beginning. It will help you go smoother and faster pace. **
If you are using command line tools to write your programs, take a close look at oracle documentation
Specially -cp parameter
You have to provide a folder where java can find compiled class files, that's what -cp is used for. For your case, java seems not to be able to find other .class files (Animal, or Dog etc).
Polymorphism Concept
Dog, Fish and a Bird are all animals. So they all inherit some basic concepts. For example all of them move. However a dog runs, a fish swims and a bird flies. Let me show you how it is done in OO:
abstract class Animal{
move();
}
class Dog extends Animal{
private run(){
...
// implementation
...
}
public move(){
run();
}
}
class Bird extends Animal{
private fly(){
...
implementation
}
public move(){
fly();
}
}
class Fish extends Animal{
private swim(){
...
implementation
}
public move(){
swim();
}
}
I hope it makes sense =]
PS: Above code is pseudo code, Not Java
1) an public animal class must be created
2) both a dog and a cat sub-class must be created, both must extend animal. Extending from animal will allow both dog and cat to accept the "add" method.
I am refactoring a huge if statement I have. One of the ways I found to improve it was by using polymorphism and inheritance. In a very simplified way, this is what I have in my code:
public abstract class Animal {
public abstract void doAction();
}
public class Dog extends Animal {
public void doAction() {System.out.println("run");}
}
public class Cat extends Animal {
public void doAction() {System.out.println("sleep");}
}
public class RunActions {
public void runAction(Dog d) {
d.doAction();
}
public void runAction(Cat c) {
c.doAction();
}
}
public class Start {
public static void main(String args[]) {
Animal animal = new Dog();
new RunActions().runAction(animal); // Problem!
}
}
I know, I know. I could just call animal.doAction();. Or add a method in RunActions that receives Animal as a parameter.
But why doesn't the compiler allow me to call that last "runAction(animal)" line? Shouldn't the JVM figure out animal is an instance of Dog in runtime?
Is there an specific reason why it doesn't allow me to do that?
EDIT: Forgot to make Dog and Cat extend Animal. Fixed.
The compiler can't guarantee that there is an appropriate method at runtime.
You have a method that takes a Cat and you have a method that takes a Dog. You are trying to pass an Animal variable that references a Dog. What if would reference an Elephant? Then there would be no suitable method at runtime. That's why it won't let you compile.
Animal animal = new Elephant();
new RunActions().runAction(animal); // real problem now!
The main underlying concept that makes what you want impossible is that Java is a single-dispatch language, just like almost all other languages called "OOP". What this means is that the runtime decision which method to call takes into account only the first method argument, which is syntactically placed before the dot, the one whose value will be bound to the this special variable.
You may also wonder why single dispatch is used in most languages... this has to do with the basic idea of encapsulation and objects being owners of their methods. Consider your case: should runAction belong to RunActions or Animal? It belongs to both equally; better stated: it doesn't belong to either. This brings about a completely different programming model, one without encapsulation.
First of all, Dog and Cat should extend Animal:
public class Dog exttends Animal{
#Override
public void doAction() {System.out.println("run");
}
And use:
public class RunActions {
public void runAction(Animal a) {
a.doAction();
}
}
As both Dog and Cat are Animals, you can use Animal argument.
The problem is not all Animals may be Cats or Dogs. Consider:
public class Fish implements Animal{
public void doAction() {System.out.println("swim");
}
What would you expect your RunActions class to do?
That's why the compiler is complaining.
There are a few approaches you can use to make your situation work. The simplest is to have one method that accepts Animal and use a series of instanceof tests to figure out what you want to do with each specific subclass of Animal.
Better do following
public interface Animal {
public void doAction();
}
public class Dog implements Animal{
public void doAction() {System.out.println("run");
}
public class Cat implements Animal{
public void doAction() {System.out.println("sleep");
}
public class RunActions {
public void runAction(Animal d) {
d.doAction();
}
}
public class Start {
public static void main(String args[]) {
Animal animal = new Dog();
new RunActions().runAction(animal);
}
}
Firstly, you are not extending Animal in Dog and Cat. So do that first.
In inheritance ISA principal gets followed.
so for example
public class Dog extends Animal
here Dog extends Animal so that DOG IS ANIMAL but the reverse is not true ANIMAL CANNOT BE NECESSARILY A DOG. IT CAN BE CAT ALSO IN YOUR CASE.
So when you pass a reference of animal to the method which accepts a DOG or a CAT assignment would be something like
Dog d=animal;
which is read as animal is DOG and that is not true.
So compiler will not allow you to do that.
And regarding why Java doesn't allow that thing to be done is to achieve the features that it is capable of achieving.
Say for example, Java allows you to pass the animal object to the method and allows you to execute the method.
so in that case
Animal animal=new Dog();
Dog d= animal;
d.doSomething(); // let's say java allowed this no problem since animal is DOG.
BUT,
Animal animal=new Horse();
Dog d= animal;
d.doSomething(); // Can you imagine what will happen in this case?
So to avoid such situaltion java is intelligent enough to stop you when you are doing wrong. Hope this clears your doubt and help you to understand this.
I wonder why it is allowed to have different type of object reference?
For example;
Animal cow = new Cow();
Can you please give an example where it is useful to use different type of object reference?
Edit:Cow extends Animal
This is at the heart of polymorphism and abstraction. For example, it means that I can write:
public void handleData(InputStream input) {
...
}
... and handle any kind of input stream, whether that's from a file, network, in-memory etc. Or likewise, if you've got a List<String>, you can ask for element 0 of it regardless of the implementation, etc.
The ability to treat an instance of a subclass as an instance of a superclass is called Liskov's Substitution Principle. It allows for loose coupling and code reuse.
Also read the Polymorphism part of the Java tutorial for more information.
On a simpler note, this enables polymorphism. For example you can have several objects that derive from Animal and all are handle similar.
You could have something like:
Animal[] myAnimal = {new Cow(), new Dog(), new Cat()};
foreach (Animal animal in myAnimal)
animal.Feed();
The Feed() method must then be overriden within each child class.
By the way, code is C#-like but concept is the same in Java.
This is basically a concept of standardization.
We know that each animal have some common features. Let us take an example of eating and sleeping, but each animal can have different way of eating or sleeping ... then we can define
public abstract class Animal
{
public abstract void Eat();
public abstract void Sleep();
}
//Now Define them in various classes..
public class Cow extends Animal
{
pubic void Eat()
{
//process of eating grass
}
public void Sleep()
{
//process of sleeping
}
}
public class Lion extends Animal
{
public void Eat()
{
//process of eating flesh
}
public void Sleep()
{
//process of sleep
}
}
Now you do not have to define different objects to different classes... just use Animal and call generally
public class MyClass
{
public static void main(String[] args)
{
Animal _animal = new //think the type of animal is coming dynamically
//you can simply call
_animal.Eat();
_animal.Sleep();
// irrespective of checking that what can be the animal type, it also reduces many if else
}
}
This is called polymorphism and it's one of the most powerful aspects of Java.
Polymorphism allows you to treat different objects the same.
It's a great way to create re-usable, flexible code.
Unfortunately it's a part of Java that new programmers often take awhile to understand.
The example you've provided involves inheritance (extending a class).
Another way to enjoy the benefits of polymorphism is to use interfaces.
Different classes that implement the same interface can be treated the same:
class Dog extends Animal implements Talker {
public void speak() {
System.out.println("Woof woof");
}
}
class Programmer implements Talker {
public void speak() {
System.out.println("Polymorphism rocks!");
}
}
interface Talker {
public void speak();
}
public static void testIt() {
List<Talker> talkerList = new ArrayList<Talker>();
talkerList.add(new Dog());
talkerList.add(new Programmer());
for (Talker t : talkerList) {
t.speak();
}
}
Simply putting all Cows are Animals. So JAVA understands that when Cow extends Animal, a Cow can also be called as Animal.
This is Polymorphism as others have pointed out. You can extend Animal with Dog and say that Dog is also an Animal.
In another class/method you might want to use different implementations of the same interface. Following your example, you might have something like:
public void feed( Animal animal ) {
animal.getHome().insertFood(animal.getFavFood());
}
Now you can implement the details in your animal classes and don't have to extend this method anytime you add a new animal to your programm.
So in some cases you need the common interface in order not to implement a method for each implementation, whereas on other occasions, you will need to use the explicit implementation.
This is an inheritance 101 question.
It allows objects that share common functionality to be treated alike.
It also allows specific implementations to be supplied at runtime that are subclasses of an abstract type.
I could probably ramble on for ages. Perhaps thus question is just too broad to answer here.