问题
So while trying to understand abstract classes, there is still one thing I am confused on. When do you ever want to declare an object type of its abstract class. For example
public abstract class GameObject
{
public abstract void draw();
public static void main(String[] args)
{
GameObject player = new Player();
Menu menu = new Menu();
}
}
public class Player extends GameObject
{
override
public void draw()
{
// Something
}
}
public class Menu extends GameObject
{
override
public void draw()
{
// Something
}
}
Normally, I would just instaniate a player object of player type. However, I have seen abstract classes used as the variable type of the new object. When would you ever choose to do this? Thanks!
回答1:
You would do that every time you need the variable to be an instance of the abstract class, but don't really care about what the concrete type is (and don't want the rest of the code to assume a specific subclass is used). For example:
GameObject[] gameObjects = new GameObject[] {new Menu(), new Player()};
drawAll(gameObjects);
...
private void drawAll(GameObject[] gameObjects) {
for (GameObject gameObject : gameObjects) {
gameObject.draw();
}
}
The abstract type is often used as a return type (because you don't want the caller to know what concrete type is returned: it could change later, or could vary based on the arguments of the configuration).
It's also often used as method parameter type, so that the method can accept an argument of any subclass of the abstract type and use it polymorphically.
And of course, as an array/collection type, to be able to store instances of multiple subclasses in a unique collection.
回答2:
Say you want to add functionality to make a particular GameObject
invisible. A raw implementation would look like:
void makeInvisible(GameObject object) { ... }
This method is supposed to work with any kind of GameObject
(and is able to make them all invisible -- or it can throw an IllegalArgumentException
if the "wrong" kind of object is passed).
Your question however seems to be particularly concerned with this kind of declaration:
GameObject gameObject = new Player(); // why on earth would you do this -- you wonder
First think of how often you've seen the following:
List<String> stringList = new ArrayList<>();
And yet, this is recommended as best practice because the rest of the code should not be aware of the particular List implementation chosen. You can change that to a LinkedList
later on without changing anything but that line above.
If you can find no reasonable scenario where such a declaration would make sense for your abstraction, it is probably a symptom for one of the following:
- You're not willing to make use of polymorphism: that is, you want to define the specific logic for each subtype and never deal with them "generically" -- like in the
makeInvisible
example above - Your abstraction isn't buying you much; in other words, it is not usable as such and you should probably re-consider your design.
In your particular case, that abstract class is not particularly well-designed.
First of all, it makes the main()
method visible to all its subclasses and there's no reason why you would want to have main
in scope for Player
or Menu
.
Secondly, it would suit better as an interface (Drawable
, maybe), since all it does is define the signature for the draw
method. This change would make its polymorphic capabilities more obvious, as you should be able to spot where you need to treat objects as mere Drawable
s and this should answer your question.
回答3:
Let's say you have an abstract Animal
class, with methods such as eat()
, sound()
, etc.
You can create classes that extend this Animal
class, let's say Dog
and Cat
.
If there are abstract methods in the abstract class (which isn't mandatory), you'll need to implement that method in each type that extends Animal
.
If the method is not abstract, you can still override it if you want it to do something different from the main class.
If you still don't fully understand try this video https://www.youtube.com/watch?v=TyPNvt6Zg8c.
来源:https://stackoverflow.com/questions/33457393/when-to-use-abstract-class-as-type