抽象类是否扩展了Object?

时间:2014-07-24 15:56:01

标签: java interface abstract-class

我已经读过接口和抽象类之间的区别,但是这个让人困惑。考虑这个接口和类。

interface I {
    public int hashCode();
    public boolean equals(Object obj);
}

class B implements I {
    // Works Fine
}

这里工作正常,我不需要覆盖接口方法,因为Object是B的超类,并且这些方法在其中实现。

现在考虑这些

abstract class A {
    public abstract int hashCode();
    public abstract boolean equals(Object obj);
}

class C extends A {
    // Compile error because methods are not overridden
}

为什么会导致编译错误?这是否意味着Object不是抽象类的超类?或者我错过了一些观点?

12 个答案:

答案 0 :(得分:33)

导致编译错误,因为根据定义,抽象函数必须在继承链中实现 downstream 。您已经创建了他们必须在A子类中实现的要求。

C没有实现这些方法,因此编译失败。

Object是抽象类的超类 ...但它不是子类,而子类负责实现抽象函数。

相反,如果一个类实现了一个接口,那么该实现可以在该类的继承层次结构中 where 。将这些实现放在超类中并不常见,因为您通常会在超类中声明接口。

在某些用例中,您可能不会像堕落/糟糕的设计那样,或者在阅读语言功能时使用这样的示例。

答案 1 :(得分:6)

正如其他人已经提到的,类A通过将它们再次声明为抽象来覆盖Object中的那些方法,因此它强制子类实现它们。

作为对您情况的澄清,请尝试按如下方式定义A

abstract class A {
    //public abstract int hashCode();
    //public abstract boolean equals(Object obj);
}

class C extends A {
    // no compile error because no abstract methods have to be overridden
}

在这种情况下,AC都继承了Object中这些方法的实现,并且没有发生编译错误。

答案 2 :(得分:3)

Object是所有类的超类,抽象与否。

我相信当你将一个类声明为abstract并在其中声明抽象方法时,你强制任何子类实现它们,无论抽象类的超类是否已经实现它们。

这与Object类无关。如果您自己创建所有类,则会得到相同的行为:

public class A {

   public int someMethod () {
       return 1;
   }
}

public abstract class B extends A {
   public abstract int someMethod ();
}

public class C extends B {

}

这将给出编译错误The type C must implement the inherited abstract method B.someMethod(),即使A已经实现了它。

答案 3 :(得分:3)

这是一个奇怪的情况,乍一看你可能会认为这是一个编译器错误来声明抽象类A。

事实上,您可能想要一些(不常见的)原因。例如,如果您想确保使用A类的每个人都实现了自己的equals和hashcode而不是依赖于Object版本,那么您可以这样做。

行为的实际解释是,为了扩展A类,您需要满足A类给您的每个要求。

在这种特殊情况下,A类说子类需要实现这些方法,超类实现它们的事实是无关紧要的,它本身就是在增加一个更具体的需求。

这里的对象没有什么特别之处:

abstract class A {
    public abstract int hashCode();
    public abstract boolean equals(Object obj);
    public void test() {

    }
 }

 abstract class B extends A {
     public abstract void test();
 }  

现在,如果您尝试定义:

class C extends B {
    public int hashCode() { return 1; }
    public boolean equals(Object ob) { return false; }
}

然后说C is not abstract and does not override abstract method test() in B

会失败

答案 4 :(得分:1)

您的抽象类只有虚拟方法(没有实现的方法)。这意味着它们存在于类的接口中,因此有人可能会实际调用它们。在您针对hashCodeequals的情况下,此类调用将导致运行时错误,因为这些方法未实现。编译器通过引发编译器错误来防止这种情况发生。

答案 5 :(得分:1)

是的,Object是抽象类的超类。您可以使用注释@Override来帮助您。

请参阅以下代码中没有错误:

abstract class A 
{   
    @Override
    public abstract int hashCode();

    @Override
    public abstract boolean equals(Object obj);
}

答案 6 :(得分:0)

每个类都扩展了Object。即使abstract类扩展了Object,但抽象类不完整。您不能实例化一个抽象类,任何扩展抽象类的类都必须提供所有缺少的方法,或者它也必须声明为abstract。

  

这会导致编译错误吗?

试一试,看看!

答案 7 :(得分:0)

每个类都扩展了Object (所有类的父亲) 这是一个编译错误,因为你必须提供一个抽象类的主体。 而你的抽象类有方法,但没有任何正文。

答案 8 :(得分:0)

每当扩展一个抽象类时,你应该确保抽象类中的所有方法都必须在子类中实现,否则会导致编译错误。

答案 9 :(得分:0)

使用接口/抽象类之前要记住的要点=>

  • 根据定义接口不能扩展类。

  • 所有类(是否抽象)隐式扩展Object作为父级

  • 如果类明确地扩展了另一个父类,则它将继承Object的方法 通过该父类的超类。

  • 扩展抽象类的类必须实现所有继承的抽象方法,或者声明为抽象类本身

就您而言, 最初在Object超类中实现的equals()和hashCode()被覆盖作为抽象类中的抽象方法隐式扩展。

因此,为避免编译错误,您必须在子类中实现继承的抽象方法或将子类本身声明为抽象。 没有别的办法。

答案 10 :(得分:0)

是的..抽象类像 Java 中的任何其他类一样扩展 Java.lang.Object 类。

当一个类没有扩展任何其他类时,编译器在编译期间插入“扩展 java.lang.Object”,这意味着,只有当一个类没有任何其他用户定义的父类时,它才会扩展 Object 类。

abstract class A {
    public abstract int hashCode();
    public abstract boolean equals(Object obj);
}

class C extends A {
    // Compile error because methods are not overridden
}

这里,C 类已经扩展了 A,所以它不会扩展 Object 类。由于您没有提供 equals 方法的实现,您将看到编译错误。

答案 11 :(得分:-2)

是抽象类确实扩展了对象类。它继承了对象类的属性。我们不应该在这里混淆抽象类不能实例化。这将发生在抽象类的子类中,但在抽象类中,我们可以实例化对象类,并且可以覆盖基本实现。因此,对象类可以从抽象类继承。