【问题标题】:Understand the logic when overriding concrete method by abstract method理解抽象方法覆盖具体方法时的逻辑
【发布时间】:2020-11-09 13:30:57
【问题描述】:

首先,我意识到用子类中的抽象方法覆盖超类中的具体方法没有多大意义。但是......因为在 Scala 中实际上可以做到这一点,所以我尝试了以下 sn-p,结果让我感到困惑。

第一个场景

  • 在超超类中被重写的具体方法
  • 抽象方法在超类中
class A {
  def x: String = "A"
}

abstract class B extends A {
  def x: String
}

class C extends B {
  def x: String = "C"
}

在 scala REPL 中执行上面的 sn-p 会导致以下错误:

  def x: String = "C"
      ^
<pastie>:10: error: `override` modifier required to override concrete member:
def x: String (defined in class A)

现在的问题是:为什么类B 中的抽象方法似乎被忽略了?但是,如果从定义中删除 C.xB.x 确实会产生影响。因为下面的sn-p也编译不了。

class A {
  def x: String = "A"
}

abstract class B extends A {
  def x: String
}

class C extends B

导致以下错误

class C extends B
      ^
<pastie>:9: error: class C needs to be abstract. No implementation found in a subclass for deferred declaration
def x: String (defined in class B)

第二种情况

  • 在超类中被重写的具体方法
  • 抽象方法在 trait 中
class A {
  def x: String = "A"
}

trait B {
  def x: String
}

class C extends A with B

尝试实例化C

scala> (new C).x
val res0: String = A

看起来B.x 抽象方法刚刚被编译器忽略了。


更新

在我的问题的第一版中,我愚蠢地忘记了在 第二个场景 中扩展 A,这导致了一个错误的结论,即类和特征在我的示例中表现不同。对于我的疏忽,我深表歉意。

让我试着重新提出我的问题:

在第一种和第二种情况下,抽象B.x在类层次结构中间的作用是什么?

据我了解,通过继承和方法解析顺序 (MRO),

  • 在第一种情况下B.x 覆盖A.xC.x 覆盖B.x。由于B.x是抽象的,当C.x实现B.x时,不需要指定override修饰符。
  • 在第二种情况下,B.x 覆盖A.xC 没有实现抽象B.x。所以C应该是抽象的,不能编译。

但在我看来,编译器只是忽略了类层次结构中间的抽象方法B.x。这种行为是在语言规范中的某个地方定义的,还是完全出乎意料和意外(并且只是一个编译器错误)?

【问题讨论】:

    标签: scala


    【解决方案1】:

    我不确定问题是关于 Traits 和 Abstract Classes 之间的差异还是关于extends 之间的差异。

    第一个场景中,您在这两种情况下都有abstract class B extends A,但在第二个场景中,您有trait Atrait BB 未扩展 A。 事实上,如果你把trait A extends B 放在第二个场景它不会编译

    第二个场景的第二种情况下,您正在扩展 2 个具有相同方法的不同特征,extends A with B 您的类定义了方法 x,因为当您从多重性状。如果您尝试以相反的顺序执行extends B with A,它将无法编译

    换句话说:

    第二种情况 - 第一种情况:定义抽象方法不需要覆盖

    第二种情况 - 第二种情况:C extends A with BB extends A + C extends B 不同

    【讨论】:

    • 嗨,很抱歉,我愚蠢地忘记在我的第二个场景代码示例中扩展 A,这误导我得出错误的结论,即类和特征在这种情况下的行为不同。我已经更新了问题描述,希望它会澄清。
    • 问题既不是关于特质和抽象类之间的差异,也不是关于扩展之间的差异。这是关于抽象方法在出现覆盖超类的相同具体方法时的效果。
    猜你喜欢
    • 2016-01-26
    • 1970-01-01
    • 1970-01-01
    • 2013-09-12
    • 2016-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-18
    相关资源
    最近更新 更多