代码之家  ›  专栏  ›  技术社区  ›  Sasha

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

  •  2
  • Sasha  · 技术社区  · 17 年前

    为什么抽象类中需要构造函数和私有成员?我们永远不会创建该类的实例。

    6 回复  |  直到 17 年前
        1
  •  14
  •   Jon Skeet    17 年前

    创建实例,只创建派生类的实例。这些派生类仍然需要调用构造函数,并且仍然可以调用抽象类的成员,而抽象类又可能使用私有成员。

    下面是一个示例(不是非常有用的示例,但只是为了说明基本想法……)

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

    我不能说我写的是抽象类 那个 通常情况下,我更喜欢组合而不是继承,但当我 创建它们我当然使用构造函数和私有成员。

        2
  •  3
  •   Rob    17 年前

    抽象类提供了一些接口的部分实现。考虑到您可能希望提供该实现的一部分,并且不允许客户端代码(具体子类)访问细节,这是完全合理的,即封装原则的扩展。

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

        3
  •  1
  •   Uri    17 年前

    与接口不同,定义数据字段的抽象类实际上是在分配这些数据字段的意义上实例化的。只是它们从来都不是自己实例化的,它们被实例化为更大的东西的一部分-子类。因此,在构建子类时,也会构建超类型,这就是为什么需要构造函数。

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

        4
  •  0
  •   Thorbjørn Ravn Andersen    17 年前

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

        5
  •  0
  •   Tom    17 年前

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

    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,但通过声明成员和构造函数,您可以自定义类的功能(这称为模板方法)。

        6
  •  0
  •   Esko    17 年前

    假设您正在执行特殊代码或原型设计,您会不时实例化抽象类(甚至接口)。它们被称为匿名内部类( one , two )如下所示:

    // 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 至少