Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 覆盖伴随对象值和Scala匹配错误_Oop_Scala_Overriding_Companion Object - Fatal编程技术网

Oop 覆盖伴随对象值和Scala匹配错误

Oop 覆盖伴随对象值和Scala匹配错误,oop,scala,overriding,companion-object,Oop,Scala,Overriding,Companion Object,有人能解释一下为什么下面的代码会导致匹配错误吗?在这种情况下,匹配错误意味着什么 class A { def g = A.f } object A { val f = "Object A" } class B extends A { override val A.f = "Object B" } val b = new B b.g 如果这不起作用,有没有办法覆盖类似于此的伴生对象val或def?首先,说明为什么会出现匹配错误。对象上的值(A.f)被视为稳定标识符(正如Sca

有人能解释一下为什么下面的代码会导致匹配错误吗?在这种情况下,匹配错误意味着什么

class A {
  def g = A.f
}

object A {
  val f = "Object A"
}


class B extends A {
  override val A.f = "Object B"
}

val b = new B
b.g

如果这不起作用,有没有办法覆盖类似于此的伴生对象val或def?

首先,说明为什么会出现
匹配错误。对象上的值(A.f)被视为稳定标识符(正如Scala引用所述,“稳定成员是由对象定义或非易失性类型的值定义引入的[…]成员”)

以下是打字机输出的样子:

object A extends scala.AnyRef {
    ...
    private[this] val f: String = "Object A";
    <stable> <accessor> def f: String = A.this.f
}
对象A扩展了scala.AnyRef{
...
private[this]val f:String=“对象A”;
def f:String=A.this.f
}
在赋值中使用时,编译器将此稳定标识符的“desugars”赋值(稳定是必要条件)转换为模式匹配:

<synthetic> private[this] val x$1: Unit = ("Object B": String("Object B") @unchecked) match {
    case A.f => ()
}
private[this]val x$1:Unit=(“对象B”:字符串(“对象B”)@未选中)匹配{
案例A.f=>()
}
它无法将“Object B”与模式“Object a”进行匹配,因此它会抛出一个
MatchError


更大的问题是:您不能/不应该覆盖伴随对象上的值和方法。多态性应用于类及其实例,而不是静态方法或值。也许有一种更好的方式来考虑您的程序,它不涉及覆盖伴生对象上的VAL/DEF。

这很有趣!如果您将类定义放入一个文件中,并使用
scalac-print test.scala
对其进行编译,您将看到如下内容:

[[syntax trees at end of                   cleanup]] // scala
package <empty> {
  class A extends Object {
    def g(): String = A.f();
    def <init>(): A = {
      A.super.<init>();
      ()
    }
  };
  object A extends Object {
    private[this] val f: String = _;
    <stable> <accessor> def f(): String = A.this.f;
    def <init>(): A.type = {
      A.super.<init>();
      A.this.f = "Object A";
      ()
    }
  };
  class B extends A {
    <synthetic> private[this] val x$1: runtime.BoxedUnit = _;
    def <init>(): B = {
      B.super.<init>();
      B.this.x$1 = {
        case <synthetic> val x1: String = ("Object B": String("Object B"));
        case5(){
          if (A.f().==(x1))
            {
              val x2: String = x1;
              matchEnd4(scala.runtime.BoxedUnit.UNIT)
            }
          else
            case6()
        };
        case6(){
          matchEnd4(throw new MatchError(x1))
        };
        matchEnd4(x: runtime.BoxedUnit){
          scala.runtime.BoxedUnit.UNIT
        }
      };
      ()
    }
  }
}
那么如何修复它呢?你可以这样做

class B extends A {
        override def g = "Object B"
}
scala> val b = new B
b: B = B@19bdb65

scala> b.g
res1: String = Object B


谢谢你的澄清!一般来说,我同意您对覆盖伴随对象的需要,但是我想在这里这样做的原因是出于测试目的,我想用另一个方法替换伴随对象中的一个方法。另外,有些语言允许重写静态方法。您的修复是绕过这个简单代码示例的一种聪明方法,但不是我真正想要的,因为我想调用原始的a.f方法。是的,traits是一种很好的方法来构造它,但在我的情况下,我想测试已经存在的代码,而不更改主代码。
class B extends A {
        override def g = "Object B"
}
scala> val b = new B
b: B = B@19bdb65

scala> b.g
res1: String = Object B
class B extends A {
        val f = "Object B"
}
scala> val b = new B
b: B = B@1e5ed7b

scala> b.f
res0: String = Object B