为什么我们需要抽象类中的构造函数和私有成员?

时间:2022-09-25 12:27:51

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 个解决方案

#1


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.

我不能说我经常编写抽象类,通常更喜欢使用组合继承,但是当我创建它们时,我当然会使用构造函数和私有成员。

#2


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.

将某些成员标记为私有强制继承类以调用受保护的方法来访问该部分实现;提供构造函数允许子类在自己构造期间初始化父级的封装状态。

#3


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.

根据您的层次结构,您的抽象类可能具有含义和状态。例如,如果您的申请是学校,您可能有一个人的概念(具有姓名和SSN),但您可以为学生和教师提供不同的子类型。因为两种类型的人共享某些状态结构(名称和SSN),所以两个类都会扩展Person类。但你永远不会直接实例化一个人。

#4


In addition to Jon's answer, I'd like to mention that abstract classes still go well with composition, if you keep the subclass tree shallow. I.e. it is great for providing a common base class for a few closely related objects, but not for creating a gigantic tree of subclasses.

除了Jon的回答之外,我还想提一下,如果你让子类树保持浅薄,抽象类仍然可以很好地用于组合。即它非常适合为一些密切相关的对象提供公共基类,但不能创建一个巨大的子类树。

#5


Why do you need private class? I think that you are confusing abstract classes with interfaces. Unlike interfaces, abstract classes can hold functionality. For example:

你为什么需要私人课程?我认为你将抽象类与接口混淆。与接口不同,抽象类可以保存功能。例如:

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

public class ConcreteDerived extends AbstractBase{

公共类ConcreteDerived扩展AbstractBase {

public ConcreteDerived(){
  super(4);
}

public int templateMethod(){
   return number; //number is the result of some calculation
}

}

In this example, you´ll never explicitly instantiate AbstractBase, but by declaring members and constructors, you can customize the functionality of your classes (this is called template method).

在此示例中,您永远不会显式实例化AbstractBase,但通过声明成员和构造函数,您可以自定义类的功能(这称为模板方法)。

#6


Assuming you're doing ad hoc code or prototyping, you do instantiate abstract classes (or maybe even interfaces) from time to time. They're called anonymous inner classes (one, two) and look like this:

假设您正在进行临时代码或原型设计,您可以不时地实例化抽象类(甚至可能是接口)。它们被称为匿名内部类(一,二),看起来像这样:

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

This example is of course quite redundant but should expose the point. Some existing frameworks even rely on the heavy usage of this behaviour, namely Apache Wicket at least.

这个例子当然是多余的,但应该揭示这一点。一些现有的框架甚至依赖于这种行为的大量使用,至少是Apache Wicket。

#1


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.

我不能说我经常编写抽象类,通常更喜欢使用组合继承,但是当我创建它们时,我当然会使用构造函数和私有成员。

#2


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.

将某些成员标记为私有强制继承类以调用受保护的方法来访问该部分实现;提供构造函数允许子类在自己构造期间初始化父级的封装状态。

#3


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.

根据您的层次结构,您的抽象类可能具有含义和状态。例如,如果您的申请是学校,您可能有一个人的概念(具有姓名和SSN),但您可以为学生和教师提供不同的子类型。因为两种类型的人共享某些状态结构(名称和SSN),所以两个类都会扩展Person类。但你永远不会直接实例化一个人。

#4


In addition to Jon's answer, I'd like to mention that abstract classes still go well with composition, if you keep the subclass tree shallow. I.e. it is great for providing a common base class for a few closely related objects, but not for creating a gigantic tree of subclasses.

除了Jon的回答之外,我还想提一下,如果你让子类树保持浅薄,抽象类仍然可以很好地用于组合。即它非常适合为一些密切相关的对象提供公共基类,但不能创建一个巨大的子类树。

#5


Why do you need private class? I think that you are confusing abstract classes with interfaces. Unlike interfaces, abstract classes can hold functionality. For example:

你为什么需要私人课程?我认为你将抽象类与接口混淆。与接口不同,抽象类可以保存功能。例如:

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

public class ConcreteDerived extends AbstractBase{

公共类ConcreteDerived扩展AbstractBase {

public ConcreteDerived(){
  super(4);
}

public int templateMethod(){
   return number; //number is the result of some calculation
}

}

In this example, you´ll never explicitly instantiate AbstractBase, but by declaring members and constructors, you can customize the functionality of your classes (this is called template method).

在此示例中,您永远不会显式实例化AbstractBase,但通过声明成员和构造函数,您可以自定义类的功能(这称为模板方法)。

#6


Assuming you're doing ad hoc code or prototyping, you do instantiate abstract classes (or maybe even interfaces) from time to time. They're called anonymous inner classes (one, two) and look like this:

假设您正在进行临时代码或原型设计,您可以不时地实例化抽象类(甚至可能是接口)。它们被称为匿名内部类(一,二),看起来像这样:

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

This example is of course quite redundant but should expose the point. Some existing frameworks even rely on the heavy usage of this behaviour, namely Apache Wicket at least.

这个例子当然是多余的,但应该揭示这一点。一些现有的框架甚至依赖于这种行为的大量使用,至少是Apache Wicket。