Why do we need constructors and private members in the abstract class? It is not like we are ever going to create an instance of that class.
6 回答
You will create instances, just instances of a derived class. Those derived classes will still need to call constructors, and can still call members of the abstract class - which may in turn use private members.
Here's an example (not a terribly useful one, but just to show the basic idea...)
public abstract class NamedObject
{
private final String name = name;
protected NamedObject(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
public class Computer extends NamedObject
{
private final int processorSpeed;
public Computer(String name, int processorSpeed)
{
super(name); // See, the constructor is useful
this.processorSpeed = processorSpeed;
}
public String toString()
{
return getName() + " (" + processorSpeed + ")";
}
}
I can't say I write abstract classes that often, generally preferring composition to inheritance, but when I do create them I certainly use constructors and private members.
Abstract classes provide a partial implementation of some interface. It's perfectly reasonable to consider that you might want to provide part of that implementation and disallow client code (concrete subclasses) from accessing the specifics - i.e. an extension of the principle of encapsulation.
Marking some members as private forces the inheriting class to call protected methods to access that partial implementation; providing a constructor allows for subclasses to initialise the parent's encapsulated state during their own construction.
Unlike an interface, an abstract class that defines data fields is in fact instantiated in the sense that these data fields are allocated. It is just that they are never instantiated on their own, they are instantiated as part of something bigger - the subclass. So when the subclass is built, the supertype is built as well, which is why you would need a constructor.
Depending on your hierarchy, your abstract class may have a meaning and state. For example, if your application is a school you may have the notion of a person (that has a name and an SSN), but you would have different subtypes for students and for faculty. Because both types of people share certain state structure (name and SSN) you would have both classes extend the Person class. But you would never simply instantiate a person directly.
假设您正在做临时代码或原型设计,您会不时实例化抽象类(甚至可能是接口)。它们被称为匿名内部类(一、二),如下所示:
// you have this...
public abstract class SomeClass {
public abstract String returnAString();
}
// ...and this...
public class OtherClass {
public void operate(SomeClass c) {
System.out.println(c.returnAString());
}
}
// ...so you do this:
OtherClass oc = new OtherClass();
// this is one of the reasons why you need to specify a constructor
oc.operate(new SomeClass() {
@Override
public String returnAString() {
return "I'm an anonymous inner class!";
}
});
这个例子当然是多余的,但应该暴露这一点。一些现有的框架甚至依赖于这种行为的大量使用,至少是Apache Wicket 。
除了乔恩的回答,我想提一下,如果您保持子类树的浅层,抽象类仍然可以很好地组合。即它非常适合为一些密切相关的对象提供公共基类,但不适用于创建巨大的子类树。
为什么需要私教?我认为您将抽象类与接口混淆了。与接口不同,抽象类可以保存功能。例如:
public class AbstractBase{
private int num;
public AbstractBase(int number){
this->num = number;
}
public int method(){
return ( this->num * this->templateMethod());
}
public abstract int templateMethod();
}
公共类 ConcreteDerived 扩展 AbstractBase{
public ConcreteDerived(){
super(4);
}
public int templateMethod(){
return number; //number is the result of some calculation
}
}
在此示例中,您永远不会显式实例化 AbstractBase,但通过声明成员和构造函数,您可以自定义类的功能(这称为模板方法)。