Run method based on input, without if-statement logic - java

I have one single method that takes in 2 parameters:
public void generate(int size, String animal){
// output a picture of the "animal" on java.swing of size "size"
}
So the possibility of the animals are Monkey, Giraffe, Dog, Cat, and Mouse. However, the assignment specifies that I can only have 1 method, no if-statements / cases / ternary operators, no external classes. So in the method, I have to create all 5 of these animals:
public void generate(int size, String animal){
// output picture of Monkey
// output picture of Giraffe
// output picture of Dog
// output picture of Cat
// output picture of Mouse
}
So in turn, I was thinking I have to only make part of the method run based on the inputs. Is there any way to do this? The professor's hint was to use "multiple dispatch", but if there is only 1 method, how is this possible?

public interface Animal {
public void draw(int size);
}
public class Monkey implements Animal {
public void draw(int size) {
// ...
}
}
etc.

Since you do not want to use if/else/switch-case , assuming each type of animal is a class you can try this implementation.
public class Test {
static Map<String, Animal> animalTypeMap = new HashMap<String, Animal>();
static {
animalTypeMap.put("Monkey", new Monkey());
// put other animals in the map
}
public static void main(String[] args) {
Test test = new Test();
test.generate(5, "Monkey");
}
public void generate(int size, String animal) {
// output picture of Monkey
Animal animalObj = animalTypeMap.get(animal);
animalObj.draw(size);
// output picture of Giraffe
// output picture of Dog
// output picture of Cat
// output picture of Mouse
}
}
interface Animal {
public void draw(int size);
// .....more methods
}
class Monkey implements Animal {
// ...implement methods
#Override
public void draw(int size) {
System.out.println("Monkey of size " + size + " drawn");
}
// ...more methods
}
// ....more classes implementing animal interface

Related

Java polymorphism in parameters

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");
}
}

Run Time Polymorphism

class A {
public void display(){
System.out.println("From Class A");
}
}
class B extends A {
public void display() {
System.out.println("From Class B");
}
}
public class Test {
public static void main(Strings[] args){
A a = new A();
A b = new B()
a.display();
b.display();
}
}
Output:
From Class A
From Class B
Now, I am getting the output as expected.
But I want to know why I am using A b = new B(), when same thing I can achieve by using
B b = new B().
What is the advantage of using former techniques, where and when it is beneficial for me?
Lets take an example here. We all know birds can fly, but there are some exceptions. We know from their behavior, so lets model this.
Generally, birds can fly, so:
class Bird {
void fly() {
System.out.println("I can fly");
}
}
class Eagle extends Bird {
void fly() {
System.out.println("I can fly very high");
}
}
We all know that ducks can't fly, but we don't say it for all birds. We say at runtime whether a specific bird can fly or not, depending on the bird.
class Duck extends Bird {
void fly() {
System.out.println("I can walk or swim only");
}
}
class FlightDemo {
public static void main(String[] args) {
Bird bird = new Bird();
bird.fly(); // output: I can fly
Bird eagle = new Eagle();
eagle.fly(); // output: I can fly very high
Bird duck = new Duck();
duck.fly(); // output: I can walk or swim only
}
}
You saw that at runtime it's decided that ducks can't fly. You can override its fly behavior and it would walk or swim. We saw that Duck IS a Bird, and it can't fly, so we have overridden its behavior, and still Duck IS a Bird, and it can walk or swim.
In your example, it doesn't matter which way you chose. Your example doesn't show the power of polymorphism.
Let's see a trivial example of Polymorphism:
interface Shape{
void draw();
}
class Rectangle implements Shape{
public void draw(){
System.out.println("Drawing Rectangle.");
}
}
class Triangle implements Shape{
public void draw(){
System.out.println("Drawing Triangle.");
}
}
class Circle implements Shape{
public void draw(){
System.out.println("Drawing Circle.");
}
}
Rectangle, Triangle, and Circle are just implementing their own definition of draw function.
Now, suppose you've to implement a drawAllShapes method in your Main class, which takes a bunch of shapes and print them all. But without polymorphism this can be hectic, as there can be different types of shapes. Now, here comes polymorphism to save us.
class RandomShapeFactory{
public static Shape createRandomShape(){
Shape randomShape;
Random random = new Random();
int randomNo = random.nextInt() % 3 + 1;
if (randomNo == 1){
randomShape = new Rectangle();
}
else if (randomNo == 2){
randomShape = new Triangle();
}
else{
randomShape = new Circle();
}
return randomShape;
}
}
class Main{
public static void main(String[] args){
Shape[] shapes = new Shape[10];
for (int i = 0; i < shapes.length; i++){
shapes[i] = RandomShapeFactory.createRandomShape();
}
drawAllShapes(shapes);
}
public static void drawAllShapes(Shape[] shapes){
for (int i = 0; i < shapes.length; i++){
shapes[i].draw();
}
}
}
This implementation of drawAllShapes doesn't have to know whether the Shape at index i is a Circle or Triangle or what, whichever Shape it is, it just calls their implementation of the draw method.
main method has all random shapes, and when passed to the drawAllShapes method, their relative implementations are invoked.
This kind of implementation also follows the Open/Closed Principle, that if you want, in future, to add some more Shapes to the hierarchy, drawAllShapes method doesn't have to know about the new shapes either, just add new classes and implement the Shape interface, and drawAllShapes will work with those shapes too.
See the above example in action here.

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!

Create an array of superclasses while maintaining polymorphic attributes

If I had an array of Birds that is filled during run-time, how can I access member methods specific to child classes?
class Bird
{
public Bird() {}
public void fly(int x) {
System.out.println("Flew "+x+" meters");
}
}
class DumbBird extends Bird
{
public DumbBird() {super();}
public void fly(int x) {
x-=5; //we're dumb
System.out.println("Flew "+x+" meters");
}
public void sing() {
System.out.println("La la la!");
}
}
public static void main(String[] args)
{
Bird[] cage = new Bird[10];
cage[0] = new Bird();
cage[1] = new Dumbbird();
cage[2] = new Sleepybird();
//.... more bird types
cage[1].sing(); //is inaccessable because it is of type Bird not DumbBird!
}
Is there a good way to be able to have a an array of generic types while being able to access member functions specific to a child class? I would like to not have to edit the Bird class.
In theory, yes. Items put in arrays are reifiable, so you could determine which type you're looking at and cast the particular object to it's actual type. This isn't a very clean solution, though, so I wouldn't recommend it.
You may consider having an abstract class or interface representing bird that has methods most birds would support, along with a check method canSing() or canFly(). Birds that don't support this such as flightless birds can throw an UnsupportedOperationException if you try to call a method the bird doesn't support, but there is no easy way to generically reference all of the birds and know about all of the different methods each sub-type of bird can have.
Just to remove my answer from the comments.
Switch to using lists instead of arrays and when you pull your specific bird out, you will need to cast it to the correct type of "Bird", see the below code example:
import java.util.ArrayList;
class Bird
{
public void fly(int x) {
System.out.println("Flew "+x+" meters");
}
}
class DumbBird extends Bird
{
public void fly(int x) {
x-=5; //we're dumb
System.out.println("Flew "+x+" meters");
}
public void sing() {
System.out.println("La la la!");
}
}
class Test {
public static void main(String[] args) {
ArrayList<Bird> cage = new ArrayList<Bird>();
cage.add(new Bird());
cage.add(new DumbBird());
cage.add(new Bird());
cage.add(new DumbBird());
cage.add(new SleepyBird());
((DumbBird) cage.get(1)).sing();
}
}

When override a method, say(), and then run the program I do not get what I anticipated to be printed

I have a superclass pet with the following code:
package pet;
public class pet {
int age;
float weight;
float height;
String color;
public void sleep(){
System.out.println(
"Good night, see you tomorrow");
}
public void eat(){
System.out.println(
"I'm so hungry...let me have a snack like nachos");
}
public String say(String aWord){
String petResponse = "OK!! OK!! " + aWord;
return petResponse;
}
}
I created subclass to pet, Fish:
package pet;
public class Fish extends pet {
public static void main(String[] args) {
// TODO Auto-generated method stub
Fish myLittleFish = new Fish();
myLittleFish.sleep();
}
public String say(String something) {
return "Don't you know fish do not talk?";
}
}
Then I created another class FishMaster:
package pet;
public class FishMaster {
public static void main(String[] args) {
Fish myFish = new Fish();
myFish.say("Hello");
}
}
When I run FishMaster it does not output: Don't you know fish do not talk?
It does not output anything.
Why is that? What do I need to put to make it output: Don't you know fish do not talk?
This is a lesson from a book, Java Programming for Kids, Parents and Grandparents, that I found the link to from another question.
say returns a String but you dont display it
System.out.println(myFish.say("Hello"));
That's because you aren't printing anything, you are just returning a String.
Try changing your main method:
public static void main(String[] args) {
Fish myFish = new Fish();
System.out.println(myFish.say("Hello"));
}
The line myFish.say("Hello") should be enclosed in System.out.println() myFish.say() is simply returning a String, but doing nothing with it. You need to print whatever is returned by say()
What do I need to put to make it output: Don't you know fish do not talk?
make your say() method like this
public void say() {
System.out.println("Don't you know fish do not talk?");
}
and call it this way
Fish myFish = new Fish();
myFish.say();
Your say() method currently only returns a string, you will need to either print the returned string
or include a print in your say() method.

Categories