【问题标题】:Is this a valid abstract class?这是一个有效的抽象类吗?
【发布时间】:2016-09-07 14:10:26
【问题描述】:

这是一个有效的抽象类吗?

我知道抽象类不能被实例化,所以我对实例变量language和构造函数Programmer持怀疑态度。它还实现了一个未声明为defaultwriteCode 方法。如果我没记错的话,可以在抽象类中实现的唯一方法是那些具有默认实现的方法。

public abstract class Programmer {
     private String language;
     public Programmer (String language) {
          this.language = language;
     }
     public void writeCode() {
          System.out.println("Written in " + language);
     }
}
  • 如果它是一个有效的抽象类,有人可以解释为什么它包含构造函数吗?

  • 另外,更广泛地说,抽象类可以有实例变量吗?如果是这样,为什么?这似乎与不能实例化抽象类的想法背道而驰吗?

  • 最后,如果有人使用writeCode 方法,我会很高兴。为什么在没有default 修饰符的情况下实现它?

谢谢!

【问题讨论】:

  • 是的!子类需要在他们的构造函数中第一次调用super(languaje);
  • 你似乎混淆了interfacesabstract classes
  • 任何类都可以声明为abstract(可能没有意义,但绝对合法)。
  • 你可能应该研究一下default修饰符到底是什么。
  • 您应该真正定义“有效”的含义以获得更好的答案。因为在一个非常基本的层面上,你可以说它是否编译,它是有效的。并且你可以通过简单的编译来检查它是否编译。

标签: java constructor abstract-class default abstract


【解决方案1】:

是的,这是一个有效的abstract 类。

抽象类可以有构造函数、实例变量和具体方法。

与常规类的主要区别在于它们可以声明abstract方法,将实现委托给非抽象子类(这里不是这种情况,你没有abstract方法)。

另一个区别是它们不能直接初始化,即使它们确实提供了一个可访问的构造函数。

抽象类的构造函数通常用于在内部初始化值,以及从子类或匿名调用。

请参阅文档here

示例

鉴于...

public abstract class Programmer {
    private String language;

    public Programmer(String language) {
        this.language = language;
    }

    public void writeCode() {
        System.out.println("Written in " + language);
    }
}

...和...

public class JavaProgrammer extends Programmer {
    public JavaProgrammer() {
        super("Java");
    }
}

具体的子类

new JavaProgrammer().writeCode(); // prints "Java"

匿名类(注意空类主体{}

new Programmer("JavaScript"){}.writeCode(); // prints "JavaScript"

【讨论】:

    【解决方案2】:

    正如你所说,抽象类不能被实例化。然而,当任何抽象类的子类被创建时,其构造函数中的第一句话就是调用super(),它只不过是其父类抽象类的构造函数的一种表示。

    一个抽象类可以有实例变量和方法。甚至可以有一个没有任何抽象方法的抽象类。但是,抽象方法只能在抽象类中声明。

    您正在混合抽象类和接口概念。接口不能有实例变量,任何实现的方法都必须以 static 或 default 修饰符为前缀。

    【讨论】:

      【解决方案3】:

      这是抽象类的正确示例。回答您的问题:

      • 在接口中使用默认关键字(从 java 8 开始),您可以在其中实现默认方法实现,抽象类可以像任何普通 java 类一样具有方法实现

      • 在抽象类中具有构造函数会强制在扩展类中具有构造函数,以便可以正确构造底层抽象类(例如,实例化字段等)

      • 抽象类不能被实例化,但任何其他类都可以有私有字段并在内部使用它们,如果它们受到保护,那么扩展类也将能够直接访问它们。

      在我看来,您将抽象类与接口混淆了。

      【讨论】:

        【解决方案4】:

        抽象类包含一个构造函数,因为在创建基于抽象类的实例化类时,它将调用super() 来执行抽象类中的代码。

        实例变量也是类似的东西。然后从抽象类开发的类可以访问language 并能够使用它。

        就默认而言,这将是最佳实践,但没有绝对要求它存在。

        【讨论】:

          【解决方案5】:

          抽象类是部分实现。有时,就像上面的例子一样,唯一阻止类被实例化的是abstract 修饰符本身!

          如果抽象类具有构造函数,则意味着子类必须调用其中一个构造函数(通过在其构造函数中调用super(...)


          更广泛地说,您似乎在混淆接口和抽象类。接口是一种契约,它们指定一个类的行为方式,但不提供任何实现。抽象类是某些代码的特定部分实现。

          当您需要其他人提供行为但您不在乎它如何工作时,会(广泛地)使用接口。当您想帮助人们提供行为时使用抽象类,但您仍然需要他们提供一些细节。

          由于这些定义重叠,因此同时提供抽象类和接口并不罕见,例如java.swing.* 中的各种适配器。

          【讨论】:

          • “Java 中的抽象类可以是完全可实例化的类”令人困惑或完全错误,因为我们无法实例化抽象类。我们可以实例化其他不再是抽象的类,而是显式或隐式扩展抽象类(如匿名类)。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-09-25
          • 1970-01-01
          • 2014-03-25
          • 2016-11-24
          • 2010-11-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多