Java polymorphism in parameters - java

I've ran into a problem with polymorph function calls. I have checked other questions, but those only asked about functions without parameters. In my case, I would need to use parameters, so it decides which method to run, depending on the input parameter's class.
What I want to do is to have a list of Animals, that's filled with dogs, cats, etc.., and when I call each .hits(otherAnimal) method, it should run the function with the other animal's class as input parameter. Eg: dog hits cat -> dog.hits(Cat c) should be called.
For the iteration through the Animal list, I need the hits(Animal a) abstract function, else it doesnt work.
But because of that, now only the .hits(Animal a) function is called, instead of the one with the given children as parameter.
I know I am doing something wrong, just can't figure out, what. Hope someone can enlighten me!
Maybe the example code does a better explanation of what it want to do, so here it is:
public class PolyTest {
public static void main(String[] args) {
LinkedList<Animal> aList = new LinkedList<Animal>();
aList.add(new Dog(4,"wof"));
aList.add(new Cat(3, "mewoo"));
//every animal hits itself and every other animal
for(int i=0; i<aList.size(); i++) {
for(int j =0; j<aList.size(); j++) {
aList.get(i).hits(aList.get(j));
}
}
}
}
Animal class:
public abstract class Animal {
int legNum;
String sound;
public Animal(int legNum, String sound) {
this.legNum = legNum;
this.sound = sound;
}
abstract void hits(Animal a);
}
Dog
public class Dog extends Animal{
public Dog(int legNum, String sound) {
super(legNum, sound);
}
#Override
public void hits(Animal a) {
System.out.println("Dog: Animal case");
}
public void hits(Dog d) {
System.out.println("Dog: pats other dog head");
}
public void hits(Cat c) {
System.out.println("Dog: hits cat");
}
}
Cat
public class Cat extends Animal {
public Cat(int legNum, String sound) {
super(legNum, sound);
}
#Override
public void hits(Animal a) {
System.out.println("Cat: Animal case");
}
public void hits(Cat c) {
System.out.println("Cat: Purrs with cat");
}
public void hits(Dog d) {
System.out.println("Cat: Runs away");
}
}

Related

How can I structure my classes which usually need to be called together?

I have some related classes that implement the same method
class Dog {
public void speak() { System.out.println("Bark") }
}
class Cat {
public void speak() { System.out.println("Meow") }
}
90% of the time, users would want both the dog and the cat to speak. They don't want to know the details. When we add a new animal, they'll want it to speak too. The idea is to avoid:
// All animals need to be explicitly told to speak every time
new Dog().speak();
new Cat().speak();
// But we just added Birds, and the users need to remember to add this call everywhere
new Bird.speak();
I could do something like
class Animals {
public void speak() {
new Dog().speak();
new Cat().speak();
new Bird().speak();
}
}
So that users can just call new Animals().speak() every time.
However, 10% of the time, it does need to be configurable. What I want is a way for users to do something like this
// Used most of the time
Animals.withAllAnimals().speak();
// Sometimes they don't want cats, and they want the dogs to woof instead
Animals.exclude(Cat)
.configure(Dog.sound, "Woof")
.speak();
How can I structure my classes to accomplish this?
I know that it is question tagged with java. However, let me show an example with C# as these languages have many common things.
The first thing is I would use inheritance and create abstract class Animal as common behaviour Speak() is used. So, abstract class should define behavior, and the derived classes should implement that behavior:
public abstract class Animal
{
public abstract void Speak();
}
Then just use inheritance and override behaviour in derived classes:
public class Bird : Animal
{
public override void Speak()
{
System.Console.WriteLine("I am a bird!");
}
}
public class Cat : Animal
{
public override void Speak()
{
System.Console.WriteLine("I am a cat!");
}
}
public class Dog : Animal
{
public override void Speak()
{
System.Console.WriteLine("I am a dog!");
}
}
Then we need a class that allows to speak for all animals. Let's create Choir class for this purpose:
public class Choir
{
private List<Animal> choristers;
public void AddChoristers(IEnumerable<Animal> choristers)
{
if (choristers == null)
choristers = new List<Animal>();
choristers.AddRange(choristers);
}
public void SpeakAll()
{
foreach (Animal animal in choristers)
animal.Speak();
}
public void Speak(Func<Animal, bool> filter)
{
IEnumerable<Animal> filteredAnimals = choristers
.Where(filter ?? (animal => true));
foreach (Animal animal in filteredAnimals)
animal.Speak();
}
}
Pay attention to Speak() method. It can take a predicate as a parameter, so you can choose desired animals to speak().
Here are some ideas.
import java.util.*;
import java.util.function.Consumer;
/**
* An animal can either speak with its own voice, or another supplied
*/
interface Animal {
String speak();
String speak(String voice);
}
/**
* Base class for animal implementations.
*
* An animal is added to a Menagerie when created.
*/
abstract class BaseAnimal implements Animal {
private final String defaultVoice;
public BaseAnimal(Menagerie menagerie, String defaultVoice) {
this.defaultVoice = defaultVoice;
menagerie.add(this);
}
public String speak(String voice) {
return voice;
}
public String speak() {
return speak(defaultVoice);
}
}
/**
* A Dog. Even when given a voice the dog does things slightly differently.
*/
class Dog extends BaseAnimal {
public Dog(Menagerie menagerie) {
super(menagerie, "Bark!");
}
public String speak(String voice) {
return voice + " (and drools)";
}
}
/**
* A collection of animals. We can do something side-effectful to each, or create a new collection where
* some classes of animal are excluded or have different behaviour.
*/
interface Animals {
void forEach(Consumer<Animal> action);
Animals exclude(Class<Animal> clazz);
Animals configureVoice(Class<Animal> clazz, String voice);
}
/**
* An Animals instance which can contain only a single animal of each class
* (an arbitrary decision based on the code in the question)
*/
class Menagerie implements Animals {
Map<Class<? extends Animal>,Animal> animals = new HashMap<>();
public Menagerie() {
}
public Menagerie(Map<Class<? extends Animal>, Animal> animals) {
this.animals = new HashMap<>(animals);
}
public void add(Animal animal) {
animals.put(animal.getClass(), animal);
}
public void forEach(Consumer<Animal> action) {
animals.values().forEach(action);
}
#Override
public Animals exclude(Class<Animal> clazz) {
Menagerie m = new Menagerie(animals);
m.animals.remove(clazz);
return m;
}
/**
* Return an Animals instance which contains a proxy for a particular type of animal
* which will behave differently when speak() is called.
*/
#Override
public Animals configureVoice(Class<Animal> clazz, String voice) {
Menagerie m = new Menagerie(animals);
Animal a = m.animals.get(clazz);
if (a != null) {
m.animals.put(clazz, new Animal() {
#Override
public String speak() {
return voice;
}
#Override
public String speak(String voice) {
return a.speak(voice);
}
});
}
return m;
}
}

Casting & Inheritance in Java [duplicate]

How can I call the eat and drink method of the Animal class with the myAnimal instance in the code?
public class Animal {
public void eat() {
System.out.println("Animal Eats");
}
public void drink() {
System.out.println("Animal Drinks");
}
}
public class Cat extends Animal {
#Override
public void eat() {
System.out.println("Cat Eats");
}
#Override
public void drink() {
System.out.println("Cat Drinks");
}
public static void main(String[] args) {
Cat myCat = new Cat();
myCat.eat();
myCat.drink();
Animal myAnimal = myCat;
myAnimal.eat();
myAnimal.drink();
}
}
Output that I am getting:
Cat Eats
Cat Drinks
Cat Eats
Cat Drinks
This is my expected output:
Cat Eats
Cat Drinks
Animal Eats
Animal Drinks
You cannot do what you want. The way polymorphism works is by doing what you are seeing.
Basically a cat always knows it is a cat and will always behave like a cat regardless of if you treat is as a Cat, Felis, Felinae, Felidae, Feliformia, Carnivora, Theria, Mammalia, Vertebrata, Chordata, Eumetazoa, Animalia, Animal, Object, or anything else :-)
Here you will have an option to choose which method do you want to invoke:
public class Cat extends Animal {
public void superEat() {
super.eat();
}
public void superDrink() {
super.drink();
}
#Override
public void eat() {
System.out.println("Cat Eats");
}
#Override
public void drink() {
System.out.println("Cat Drinks");
}
}
This line:
Animal myAnimal = myCat;
assigns the variable myAnimal to the object myCat, which you've created before. So when you call myAnimal.eat() after that, you're actually calling the method of the original myCat object, which outputs Cat Eats.
If you want to output Animal Eats, you'll have to assign an Animal instance to a variable. So if you would do this instead:
Animal myAnimal = new Animal()
the variable myAnimal will be an instance of Animal, and thus will overwrite the previous assignment to Cat.
If you will call myAnimal.eat() after this, you're actually calling the eat() method of the Animal instance you've created, which will output Animal Eats.
Concluding: your code should read:
public class Cat extends Animal {
#Override
public void eat() {
System.out.println("Cat Eats");
}
#Override
public void drink() {
System.out.println("Cat Drinks");
}
public static void main(String[] args) {
Cat myCat = new Cat();
myCat.eat();
myCat.drink();
Animal myAnimal = new Animal();
myAnimal.eat();
myAnimal.drink();
}
}
Access to static fields, instance fields and static methods depends on the class of reference variable and not the actual object to which the variable points to.
Remember that member variables are shadowed, not overridden.
This is opposite of what happens in the case of instance methods.
In case of instance methods the method of the actual class of the object is called.
class ABCD {
int x = 10;
static int y = 20;
public String getName() {
return "ABCD";
}
}
class MNOP extends ABCD {
int x = 30;
static int y = 40;
public String getName() {
return "MNOP";
}
}
public static void main(String[] args) {
System.out.println(new MNOP().x + ", " + new MNOP().y);
ABCD a = new MNOP();
System.out.println(a.x); // 10
System.out.println(a.y); // 20
System.out.println(a.getName()); // MNOP
}
In this example although the the object myCat is assigned to an Animal object reference, (Animal myAnimal = myCat) the Actual object is of type Cat and it behaves as it's a cat.
Hope this helps.
You can create constructor for class Animal, that takes another Animas as parameter, and creates new instance based on provided one.
public class Animal {
//some common animal's properties
private int weight;
private int age;
public Animal() {
// empty.
}
public Animal(final Animal otherAnimal) {
this.weight = otherAnimal.getWeight();
this.age = otherAnimal.getAge();
}
public void eat() {
System.out.println("Animal Eats");
}
public void drink() {
System.out.println("Animal Drinks");
}
// setters and getters.
}
public class Cat extends Animal {
#Override
public void eat() {
System.out.println("Cat Eats");
}
#Override
public void drink() {
System.out.println("Cat Drinks");
}
public static void main(String[] args) {
Cat myCat = new Cat();
myCat.eat();
myCat.drink();
// note: myAnimal is not a Cat, it's just an Animal.
Animal myAnimal = new Animal(myCat);
myAnimal.eat();
myAnimal.drink();
}
}
Few suggestions :
Don't pass child class reference to super class and except super class method has to be invoked for overridden method. Call super class methods from super class instance.
Animal myAnimal = new Animal();
myAnimal.eat();
If you want to call super class method from child class, explicitly call super class method name with super.methodName();
public void eat() {
super.eat();
System.out.println("Cat Eats");
}
Don't override super class method in child class. Always super class method is invoked.
If you make methods in each class static, it should work.
public class Animal {
public static void eat() {
System.out.println("Animal Eats");
}
public static void drink() {
System.out.println("Animal Drinks");
}
}
public class Cat extends Animal {
#Override
public static void eat() {
System.out.println("Cat Eats");
}
#Override
public static void drink() {
System.out.println("Cat Drinks");
}
public static void main(String[] args) {
Cat myCat = new Cat();
myCat.eat();
myCat.drink();
Animal myAnimal = myCat;
myAnimal.eat();
myAnimal.drink();
}
}
The above code will give the following output
Cat Eats
Cat Drinks
Animal Eats
Animal Drinks
You can achieve what you want using the super keyword, which allows to access the overridden method.
public class Animal {
public void eat() {
System.out.println("Animal Eats");
}
public void drink() {
System.out.println("Animal Drinks");
}
}
public class Cat extends Animal {
public void eat() {
System.out.println("Cat Eats");
}
public void drink() {
System.out.println("Cat Drinks");
}
public void printMessage(){
super.eat();
super.drink();
}
public static void main(String[] args) {
Cat myCat = new Cat();
myCat.eat();
myCat.drink();
myCat.printMessage();
}
}
Please don't vote on this answer... you can vote on the other one :-) This is a bad answer, but shows how you would do what you are trying to do... poorly.
public class Main
{
public static void main(final String[] argv)
{
Child child;
Parent parent;
child = new Child();
parent = child;
child.a();
parent.a();
child.otherA();
parent.otherA();
}
}
class Parent
{
public void a()
{
System.out.println("Parent.a()");
}
public void otherA()
{
// doesn't matter what goes here... really should be abstract
}
}
class Child
extends Parent
{
#Override
public void a()
{
System.out.println("Child.a()");
}
#Override
public void otherA()
{
super.a();
}
}
public class Main {
public static void main(String[] args) {
Cat myCat = new Cat();
myCat.eat();
myCat.drink();
Animal myAnimal = new Animal();
myAnimal.eat();
myAnimal.drink();
}
}
public class Animal {
public void eat(){
System.out.println("Animal eat() called");
}
public void drink(){
System.out.println("Animal drink() called");
}
}
public class Cat extends Animal {
#Override
public void eat() {
System.out.println("Cat eat() called");
}
#Override
public void drink() {
System.out.println("cat drink() called");
}
}
OUTPUT:
Cat eat() called
cat drink() called
Animal eat() called
Animal drink() called
You need to create an object of the super class Animal OR another option is to use the keyword super in the child class methods e.g., super.eat() or super.drink()
Cat can't stop being a cat, even if it is an animal. Cat will eat and cat will drink in a cat's way. It might be similar to what an Animal does, which is why it overrides the method. If you want it to do what the animal does by default, don't override. You could probably do some weird stuff with reflection and make separate methods that access the parent methods such as:
public void superDrink() {
Animal.class.getMethod("drink").invoke();
}
but that might be overkill don't you think?
Of course that probably wouldn't work since it's not static.
You can do what you want with a few minor changes to your code. Naturally the methods of the Animal class have been overriden and you cannot simply access them by changing the reference type. Instead, you could slightly change the definition of the eat and drink functions as follows.
class Animal{
public void eat(boolean randomBoolean){
System.out.println("Animal eats");
}
public void drink(boolean randomBoolean){
System.out.println("Animal drinks");
}
}
class Cat extends Animal{
public void eat(boolean wantOverriden){
if(wantOverriden){
boolean randomBooleanValue=true|false;
super.eat(randomBooleanValue);
}
else{
System.out.println("Cat eats");
}
}
public void drink(boolean wantOverriden){
if(wantOverriden){
boolean randomBooleanValue=true|false;
super.drink(randomBooleanValue);
}
else{
System.out.println("Cat drinks");
}
}
}
Now you should be able to access the overriden methods of the Animal class through the Cat class object by simply passing in a boolean value indicating if you want to do so ex:
Cat c=new Cat();
c.eat(false); //Indicating that you dont want to access the overriden method
c.drink(false); //Indicating that you dont want to access the overriden method
c.eat(true); //Indicating that you want to access the overriden method
c.drink(true); //Indicating that you want to access the overriden method

how to pass more types arguments into method with one parameter

I have several classes with differently object type cat, dog and horse. I have
one root class where is method doSomethig with only one parameter which I want to call in rest of classes. How to write the method without type conflict. This is only example.
Cat cat;
Dog dog;
Horse horse;
protected void doSomething(one parameter){
cat.doMeow();
dog.doBark();
horse.run();
}
Why not to extend parent class Animal where there would be doSomething(one parameter) and then in subclasses call super() ?
If I understand you right, the signature is fixed for just one parameter. But you need to have access to cat, dog and horse? In that case, you need to adjust one to be a parameter object.
(Also, it should start with an upper case letter, as general accepted code style)
public class one
{
private Cat cat;
private Dog dog;
private Horse horse;
public one(Cat cat, Dog dog, Horse horse)
{
this.cat = cat;
this.dog = dog;
this.horse = horse;
}
public Cat getCat()
{
return this.cat
}
// getDog(), getHorse()
}
Then use the getter methods in the doSomething method
protected void doSomething(one parameter){
parameter.getCat().doMeow();
parameter.getDog().doBark();
parameter.getHorse().run();
}
Calling it like:
public void myMethod()
{
one animals = new one(new Cat(), new Dog(), new Horse());
doSomething(animals); // if same class or myInstance.doSomething(animals) if another class
}
A brute force solution would be to pass an Object, e.g. of type Animal and check the type in the method, and call the appropriate method based on the result of the type check:
protected void doSOmething(Animal an Animal) {
if( anAnimal instanceof Horse)
((Horse) anAnimal).run();
else if( anAnimal instanceof Dog )
((Dog) anAnimal).bark();
else ...
}
However, this is considered to be bad style, because the method has too much knowledge about Horses, Dogs, and such.
It would be better if Animal had an abstract method doDefaultAction() which is overwritten by the Horse as a call to run(), by the dog as a call to bark(), and so on.
abstract class Animal {
abstract void doDefaultAction(Animal anAnimal);
}
class Horse extends Animal {
#Override
void doDefaultAction(Animal anAnimal) {
((Horse) anAnimal).run();
}
void run() { /* do some running */ }
}
In your method doSomething() you would simply call anAnimal.doDefaultAction() without need to know what the default action for the animal might be.
If the abstract Animal class does not do something else you might also consider to use an interface Animal instead of a class.
You could create a common interface and call the interface method. For example:
public interface Animal {
public void act();
}
public class Cat implements Animal {
public void doMeow() { /* ... */ }
#Override
public void act() {
doMeow();
}
}
public class Dog implements Animal {
public void doBark() { /* ... */ }
#Override
public void act() {
doBark();
}
}
Then the doSomething method could polymorphically call the act method:
protected void doSomething(Animal animal) {
animal.act();
}
Depending on which object is passed (e.g. Cat or Dog), the behavior of doSomething will change.
Assuming this is the classic OO inheritance example. A simple solution works like this:
public class AnimalExample {
interface Animal {
void action();
}
public static class Cat implements Animal{
#Override
public void action() {
System.out.println("meow");
}
}
public static class Dog implements Animal{
#Override
public void action() {
System.out.println("bark");
}
}
public static class Horse implements Animal{
#Override
public void action() {
System.out.println("run");
}
}
static void doSomething(Animal animal){
animal.action();
}
public static void main(String[] args) {
Cat cat = new Cat();
Dog dog = new Dog();
Horse horse = new Horse();
doSomething(cat);
doSomething(dog);
doSomething(horse);
}
}

Incorporating Polymorphism

I'm new to Java and need to employ polymorphism into the following lines:
horse.feed();
horse.wash();
horse.exercise();
How do I do this?
These are the first lines of the code in this exercise:
public class Main extends Object {
public static void main(String [] args) {
Horse horse = new horse();
}
}
Answering the question from your comment: "Could someone write out how it should look so I can better understand it."
Let's create an interface Animal
public interface Animal {
public void feed();
public void wash();
public void exercise();
}
And a class Horse:
public class Horse implements Animal {
#Override
public void feed() {
// Do something to feed the horse
}
#Override
public void wash() {
// Do something to wash the horse
}
#Override
public void exercise() {
// Do something to exercise the horse
}
}
Now in your main method, you can create a horse that is an Animal and call the methods:
Animal horse = new Horse();
horse.wash();
// Etcetera
Now if you would make a class Dog, which also implements Animal, you could make a List of Animals and add Horses and Dogs to one List!

Simple Object-oriented Programming Concepts

it may looks like a dummy question for you but I have difficulties solving this:
We have an abstract class Animal and Cat and Dog that extends it. In Animal we have a method produceSound(); that is abstract. As you can probably guess for Cat it should return "Mao" and for Dog - "Bao" or something like that. This is OK but now we must write a static method in the Animal class that returns Cat or Dog objects depending on their sound. For example: identifyAnimal("Mao") should return Cat.
Question: How to implement the identifyAnimal(String sound) method?
Here is some simple example of the hierarchy:
Animal class
public abstract class Animal {
protected abstract String produceSound();
protected static void identifyAnimal(String animalSound) {
// TODO
}
}
Cat class
public class Cat extends Animal{
#Override
protected String produceSound() {
return "Mao";
}
}
Dog class
public class Dog extends Animal{
#Override
protected String produceSound() {
return "Bao";
}
}
Test class
public class AnimalTest {
public static void main(String[] args) {
Animal.identifyAnimal("Bao");
}
}
In the AnimalTest class when calling the Animal.identifyAnimal("Bao"); we should get a Dog.
private static Class[] animalTypes = [Dog.class, Cat.class];
public static String identifyAnimal(String animalSound)
{
for (int i = 0; i < animalTypes.length; i++) {
Animal a = animalTypes[i].newInstance();
String s = a.produceSound();
if (animalSound.equals(s))
return animalTypes[i].getName();
}
return null;
}
So here a (terrible) way to do this. I actually twitched a little.
I don't know what language you are using, so I'm going with c++(sorry current mode) though you could replace maps with Dictionaries if we are in C#, whatever. This is a bad way to go about things, but should work(conceptually, anyway)
Again...Terrible...
public abstract class Animal {
protected abstract String produceSound();
protected static map<string, string> SoundList;
protected static bool registerSound(string sound, string type)
{
return (SoundList.insert( pair<string, string>(sound, type)))->second;//true if worked false if already there
}
protected static string identifyAnimal(string animalSound)
{
map<string,string>::iterator result = SoundList.find(sound);
if(result != SoundList.end())
return result->second;
else
return "What The Hell Is This!?";
}
}
Cat class
public class Cat extends Animal
{
Cat()
{
Animal::registerSound("Mao","Cat");
}
#Override
protected String produceSound() {
return "Mao";
}
}
abstract class Animal {
static Map<String,String> map = new HashMap<String,String>();
public Animal(String value) { map.put(produceSound(), value); }
protected abstract String produceSound();
protected static void identifyAnimal(String animalSound) {
System.out.println(map.get(animalSound));
}
}
class Cat extends Animal {
#Override
protected String produceSound() { return "Mao"; }
Cat(){ super("CAT"); }
}
class Dog extends Animal {
#Override
protected String produceSound() { return "Bao"; }
Dog(){ super("DOG"); }
}
class Test {
public static void main(String[] args) {
new Dog();
new Cat();
Animal.identifyAnimal("Bao");
}
}
Do a switch with the predefined sounds that you have and let each sound return a string with the name of the animal. For example "Mao" returns a string "Cat" and so on.
One more thing let ur identifyAnimal method returna string instead of void.
You could use reflection to get a list of all types that extend Animal, loop through them using Activator to create instances of each type running produceSound on each until you find the return value that matches animalSound, returning that instance. Slow, but effective if you want to avoid your Animal class being aware of what extends it.
What is the nature of the problem you are trying to solve? There is no 'right' way that is independent of the problem.
What does the consuming application need from the class Animal? What does your application need to do with the classes that it consumes? Nothing can be assumed unless these presumptions are clear.

Categories