Trying to understand this polymorphism exercise - java

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.

Related

Please explain Java inheritance in this case

I'm learning Java and can't understand some tricks of inheritance.
Example:
we have a class Animal;
we have a class Cat, extends Animal;
we have a class Tiger, extends Cat;
Questions:
1) Why Cat uses Tigers method?
See below example of "make_a_sound" method. It's from Tiger, but Cat can use it.
2) Why Cat, can not see any properties of Tiger?
Cat can use method "make_a_sound" of Tiger, but can not see its properties... quite strange.
Thanks,
Gennadiy
public class Solution {
public static void main(string[] args) {
Cat cat = new Tiger();
// The result is from Tiger class: A tiger says RRRRR & new tiger property
// Why???
cat.make_a_sound();
// Only cat's and Animal's properties are visible. No Tiger's properties
System.out.println(cat.this_is_a_cat);
}
// Base class
public class Animal {
public String this_is_an_animal = "Animal";
public void make_a_sound() {
System.out.Printf("I'm an animal");
}
}
// Extends base class
public class Cat extends Animal {
public String this_is_a_Cat = "Hi, I'm a cat";
public void make_a_sound() {
System.out.Printf("A cat says meey");
}
}
// Extends prev. class
public class Tiger extends Cat {
public String this_is_a_Tiger = "Tiger";
public void make_a_sound() {
System.out.Println("A tiger says RRRRRR");
this_is_a_Tiger = "new tiger property";
System.out.println(new_tiger_property);
}
}
}
You defined cat as type Cat. That means cat can do anything that any other Cat can do. The Animal object does define the make_a_sound function so it's available to all Animal instances. When you run your code, the variable cat points to a Tiger instance so when make_a_sound is called, it's the one in Tiger that runs. That's the whole point of inheritance.
For your second question, cat is of type Cat so you can only do things with it that you can do with any Cat object. Since this_is_a_Tiger is not something every Cat object has, it is not available to cat even though cat really points to a Tiger.
But you could do this:
if (cat instanceof Tiger) {
Tiger tiger = (Tiger)cat;
System.out.println(tiger.this_is_a_Tiger);
}
Why Cat uses Tigers method? See below example of "make_a_sound" method. It's from Tiger, but Cat can use it.
Answer) Because when you say Cat cat = new Tiger() you are not saying any cat,you are saying you want sound of the Tiger and not any generic cat.Tiger is using cat's "make_a_sound" method by over riding the implementation by the Tigers sound.
if you had not overriden tigers "make_a_sound" method then the Cat's "make_a_sound" method will be called.You can try it out by saying super().make_a_sound in Tiger class or removing implementation of this method.
2) Why Cat, can not see any properties of Tiger? Cat can use method "make_a_sound" of Tiger, but can not see its properties... quite strange.
Answer) If parents classes would know everything about child class then OOPS will be broken.In OOPS each class should only know about what it does and nothing else.It does not care of other class responsibility.
This link could give you some concept regarding Overriding in Java:
https://www.geeksforgeeks.org/overriding-in-java/
For simplicity, Overriding only take effective on methods (regarding Question 1), but not on field variables (regarding Question 2).

General question about interfaces in Java [duplicate]

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();

Polymorphism in java: Why do we set parent reference to child object?

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.

Using abstract screen in LibGDX

I want to use an abstract screen for my LigGDX game. I have read many websites and many of them use abstract screen only to group the common codes (e.g. common methods) together. If this is the case, we can simply use a normal class to do the task.
The original purpose of abstract screen should be as follows:
When an abstract class is subclassed, the subclass usually provides implementations for all of the abstract methods in its parent class. However, if it does not, then the subclass must also be declared abstract.
Can someone explain this situtation.
Thanks
Abstraction allows you to have many classes that share some functionality but may differ in the implementation. You can then declare something to be the abstract class and leave the implementation up to the subclasses.
For example, maybe your program has a cat, a dog, a rat, and a spider. Well, all four of these are animals and they all share some functionality even though they're quite different in the specifics. Cats, dogs, rats, and spiders all move and they all eat but they do so very differently. You might declare an Animal abstract class and then a Spider class, a Cat class, a Dog class, and finally a Rat class all extending Animal.
public abstract class Animal {
int numLegs;
float speed; // in meters per second
int weight;
abstract void walk();
abstract void eat(Object food);
}
public class Cat extends Animal {
public Cat() {
numLegs = 4; // cats generally have 4 legs
weight = 10; // 10 pounds
speed = 13; // cat can run 13 meters per second
}
public void walk() {
// TODO: implement walking functionality for cat
}
public void eat(Object food) {
// TODO: implement check to make sure food isn't poisonous
// TODO: make cat eat food
}
}
// Similarly for other animals
public class MyProgram {
public void myWorld() {
List<Animal> animals = new ArrayList<Animal>();
animals.add(new Cat());
animals.add(new Spider());
for (Animal a : animals) {
a.move();
}
}
}
Check out this documentation for more details.

Why doesn't Java allow me to perform this type of polymorphism/inheritance?

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.

Categories