简体   繁体   中英

Java implementation of Polymorphism, casting and method overriding in Game design

Note: This is the conceptual version of my question. My actual question about the application of these concepts is shown below this chunk.


I am trying to figure out when an object is considered an instance of its own class or the class's superclass. Consider the following superclass Animal and Subclass Seahorse:

import java.util.List;
import java.util.ArrayList;
public class Animal
{
    public static void main(String[] args)
    {
        Animal a= new Animal();
        /*1. This line prints a's class*/
        System.out.println(a.getClass());

        List<Animal> animals= new ArrayList<Animal>(1);
        animals.add(new Seahorse(1));
        //2. Let's see what happens here
        animals.get(0).printClass();

        for(Animal e : animals)
        {
            e.printClass(); //3 This is an overriden method
            //e.printThisClass(); Compile Time error;
            //4. Note this method only exists in subclass
        }
        Animal hiahiahia = new Seahorse();
        hiahiahia.printClass(); //5. Lets see what happens
        hiahiahia.printThisClass(); //6. 
    }
    public void printClass()
    {
    System.out.println("Animal");
    }
}

public class Seahorse extends Animal
{
    private int y;
    public Seahorse(int a)
    {
        this.y=a;
    }
    public void printClass()
    {
        System.out.println("Seahorse");
    }

    public void printThisClass()
    {
        System.out.println("Seahorse");
    }
}

And the outputs look like this:

class Animal  //1.
Seahorse      //2.
Seahorse      //3.
Seahorse      //5.

You can see that Although Seahorse Objects are stored in Animal Objects or Lists, Polymorphism caused the Seahorse methods to be called.

However, when I try to call a method whose name only exists in the subclass on an Seahorse object disguised as a Animal object, the compile throws an error.

QUESTION: Is it true that polymorphism only works when methods override? Is there any time when

 Animal animal = new Seahorse(1);

Causes animal to be seen as an animal only(not a seahorse)?

What's the difference between

 Animal animal = new Seahorse();
 animal.printThisClass();

and

((Seahorse)animal).printThisClass();

Finally, when should I use casting?


I am working on a 2d Game and created the following class:

public class Entity
{
}

and

public class Character extends Entity
{
  //With bunch of extra fields and methods
}

I also have a controller class that has two fields:

private List<Entity>;
private List<Character>;

I separate them because Entities(in this case arrows, bullets) only collide with characters, but not with other entities. Here's the problem: I also have a render method that draws the BufferedImage of all my Entities. Now in order for the graph to make sense, the Entities should be rendered in the ascending order of their Y values.(That is, from farthest to nearest). However, this requires all characters and entities to be put in the same collection...

The question is: Should I separate them or not? If I put them in the same List, wouldn't that cause confusion because you can't tell characters from Entities?

Thanks : )

Answer to the First Question:

What's the difference between

Animal animal = new Seahorse(); animal.printThisClass(); and

((Seahorse)animal).printThisClass();

There is no difference. When you cast that animal to the Seahorse it allows you to access the methods of the Seahorse. For instance, if the Seahorse class had a method called blowBubble() if you did animal.blowBubble() (assuming animal is defined like above) it will give you an error because the Animal class does not have a method called blowBubble() .

However, when you cast the animal variable to Seahorse by doing ((Seahorse)animal) you are saying I know this animal is a Seahorse so allow me to use Seahorse's methods.

Animal animal = new Seahorse();
animal.method();
((Seahorse)animal).method(); // calls the exact same method even if it was overriden

However, you'll notice if you do this

Animal animal = new Animal();
((Seahorse)animal).blowBubbles();
((Seahorse)animal).method();

Each time you try to cast it, it will throw you a ClassCastException because an Animal cannot be transformed into a Seahorse. But, because a Seahorse is always and animal, you can call any animal methods on a Seahorse instance.

Seahorse seahorse = new Seahorse();
seahorse.methodInAnimalClass();

For your next question , having two separate lists for characters and entities is entirely up to you. Since you need to do a simple sorting algorithm for determining who has the greatest or lowest y position it probably won't matter.

You can always create a method called getAllEntities() that returns a new List that combines the entities and characters and then sort over that list and render them.

Like, the comments said, you should also look at interfaces, but I don't recommend creating tons of interfaces. I think starting simple is the way to go, however, as your game becomes for advanced, you may want to look into implementing them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM