可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am learning JAVA and following the book JAVA:The Complete Reference by Herbert Shildt.
I learned about abstract classes in Java, but could not understand reason behind this line:
An abstract class cannot be directly instantiated with new operator.
I searched over web and stackoverflow and followed these questions: Why can't we instantiate a abstract class in JAVA? and Why can't we instantiate an interface or an abstract class in java without an anonymous class method?
In one answer, someone wrote as:
Simply, in a good object oriented program, you should never want to
instantiate an abstract class or interface. If you do, the design is
probably wrong.
I do not understand why it is important not to instantiate an abstract class for good OOP
design. If someone can give a good explanation, then please help.
回答1:
An abstract class should be something that doesn't make sense if it exists completely on its own.
Take a Vehicle for example. Can you describe a Vehicle without describing a specific type of Vehicle at the same time? No - because Vehicle is just a way of describing common features and behaviours of a group of related objects. Alternatively, you could think of them as concepts.
Your quote:
Simply, in a good object oriented program, you should never want to instantiate an abstract class or interface. If you do, the design is probably wrong.
Is spot on. If you've written an abstract class that you want to instantiate completely on its own, then it isn't an abstract class. If you ever find yourself in this situation, you probably need to carry out another level of abstraction to separate out the abstract parts from the bits that actually start to condense the class into something concrete. The only thing you should want to do with an abstract class is to extend it - to turn it into something less vague (or more concrete if you prefer).
Of course, Java can seem a little contradictory at times. In fact, writing a constructor for an abstract class is perfectly valid:
abstract class Vehicle {
// You might have some common variables defined here
Vehicle() { }
}
At first this seems a little stupid. Why can I write a constructor, which is designed to allow you to instantiate an object, when I'm not allowed to instantiate the class? The compiler will even create a default constructor for you if you don't write one!
The answer there is that you are allowed to instantiate an abstract class - you're just not allowed to instantiate it directly using the new
keyword. But the most important part of abstract classes is that they're designed to be extended.
When you instantiate a subclass of an abstract class, you either explicitly or implicitly call super();
inside the constructor:
public class Car extends Vehicle {
public Car() {
super(); // If you don't put this here, the compiler will!
}
}
This actually makes sense when you think about it - you can't have a Vehicle on it's own, but my car that's sat in the car park is definitely a Vehicle. Once I have a concrete extension to my concept of a Vehicle, Car
in this case, then I can have a Vehicle.
Probably the most useful thing that this enables you to do is create generic collections. Because Vehicle is the superclass of all of the different types of Vehicle, I can say:
List<Vehicle> vehicles = new ArrayList<>();
Or if you prefer not to/can't use the diamond operator (<>
):
List<Vehicle> vehicles = new ArrayList<Vehicle>();
This allows me to put any type of Vehicle into that collection:
vehicles.add(new Car());
vehicles.add(new Van());
vehicles.add(new Lorry());
vehicles.add(new Motorcycle());
// and so on...
Although there are many other advantages to this, too numerous to cover in this answer.
回答2:
You can't instantiate an abstract class, bacause it usually contains abstract methods, which have no implementation. In order to instantiate a class, all of its methods must be implemented. Sub classes would implement the abstract methods, and you would instantiate those sub classes.
However, even if you implement all the methods, you would sometimes define the class as abstract if you want to prevent users of the class from instantiating it. You would define a class as abstract if it is meant to be sub-classed, and doesn't contain all that is required for creating a fully functional object.
As for interfaces, they just declare methods without implementation (with the exception of default methods introduced in Java8), and don't have constructors or class variables. You can't instantiate them without implementing all of their methods.
回答3:
Well, let's take an example so that you can understand why in object oriented paradigm the abstract classes are not for instantiation, but for extending :
Suppose that we want to design a Zoo Application , where we present each animal by a set of information, but each type would be presented by it's class, if we want to follow a good practice, then we create a class called Animal
where we put commons information about all animal ( id, price, entryDate...).
public abstract class Animal {
private long id;
private Date entryDate;
private double price;
private String name;
// other common info
}
This would help designing other classes from a structural point of view
public Lion extend Animal {
private boolean isFromAfrica;
}
回答4:
Abstract classes are meant to provide a skeleton structure so there is no concrete implementation in them.
The child classes are expected to fill in the implementation and hence they can be instantiated.
回答5:
Yout answer is in your given statement:
Simply, in a good object oriented program, you should never want to instantiate an abstract class or interface. If you do, the design is probably wrong.
You should never want to instantiate an abstract class.Because abstract class is an uncomplete class whose intstantiation does not make any sense.You define a behavior for classes which will extend your abstact class. It's more about a guy saying "these classes should look like that, and they got that in common, so fill in the blanks!".
Abstract classes are useful when you need a class for the purpose of
inheritance and polymorphism, but it makes no sense to instantiate the
class itself, only its subclasses. They are commonly used when you
want to define a template for a group of subclasses that share some
common implementation code, but you also want to guarantee that the
objects of the superclass cannot be created.
So it is to important to do not instantiate an abstract class as according to right design, purpose of abstract class is different,you use it when used when you want to define a template for a group of subclasses and it makes no sense to instantiate the class itself,
For example: let's say you need to create Dog, Cat, Hamster and Fish objects. They possess similar properties like color, size, and number of legs as well as behavior so you create an Animal superclass. However, what color is an Animal? How many legs does an Animal object have? In this case, it doesn't make much sense to instantiate an object of type Animal but rather only its subclasses.
回答6:
it may seem baffling at first , but you will get used to it
well technically it can't be instantiated because -
it does not contain method definitions.so y waste space on its instantiation!
theoretically-
it defeats the entire purpose of abstract class if u can instantiate it..y go thru all the trouble of creating the concept when it is no different than the ordinary class
回答7:
Abstract classes sole purpose is to be extended. The abstract class will contain common code for all its subclasses and the subclasses will only implement those sections that is relevant to it.
Abstract classes are quite useful for the Command pattern. For example, let's say you have a task that needs to execute a set of actions, then you can define a Command abstract class:
public abstract class Command
public void doCommand() {
// Actual code here doing stuff...
runInternal();
// more code;
}
public abstract void runInternal();
}
The idea now is that you can implement a whole range of commands, for example:
public void RedCommand extends Command {
public void runInternal() {
// Real code that does red things
}
}
...and also
public void BlueCommand extends Command {
public void runInternal() {
// Real code that does blue things
}
}
Now, you can have something like this:
List<Command> list = new ArrayList<>();
list.add(new RedCommand())
list.add(new RedCommand())
list.add(new BlueCommand())
for(Command c : list) {
c.doCommand();
}
Now it's easy to add more commands later, by simply extending the Command abstract class and implementing the runInternal() method. As with all things, this pattern can/is heavily abused, but in the right environment is makes for easy/readable code.
回答8:
The reason is that sometimes several concrete classes (classes that can be instantiated) all share common functionality. The common functionality can be shared through inheritance. The common methods are put in the abstract classes. The concrete subclasses can use those methods as they are defined in the abstract class, or concrete subclasses can override the methods to implement special behavior.
As analogy, think of these four things: animal, mammal, human, elephant. There are real creatures called "human" and "elephant", but there are no creatures named "animal" or "mammal". Human and elephants are concrete that way. Animals and mammals are abstractions we created to describe traits common to different creatures. Humans and elephants are kinds of mammals. Mammals are kinds of animals.
In the OO world, we could model these four things as classes. Class Mammal is an abstract class that extends the abstract class Animal. Human and Elephant are concrete classes that extend Mammal. Declaring classes Animal and Mammal as abstract tells others that there is no such thing as an "animal" or "mammal" running around in the woods. Animal and mammal are just ideas we invented to describe things that humans, elephants, and other creatures have in common.