Scala 覆盖受保护成员函数



我想实例化一个特征并覆盖受保护的函数g,使其可访问(函数f用于测试)。

trait A {
    protected def g( i: Int ) = println( i )
    def f( i: Int ) = println( i )
}

我创建了一个对象 a1

val a1= new A {
    override def f( i: Int ) = super.f(i)
    override def g( i: Int ) = super.g(i)
    def h( i: Int ) = super.g(i)
}

并尝试调用方法

a1.f(1)
a1.g(3)    // this call fails
a1.h(5)

对于 a1.g(3),我收到此错误:

<console>:10: error: method g in trait A cannot be accessed in A{def h(i: Int): Unit}
   Access to protected method g not permitted because
   enclosing object $iw is not a subclass of 
   trait A where target is defined
                      a1.g(3)    // this call fails

但是当我定义一个特征 A2 扩展 A 并覆盖方法 fg 时,创建它的实例并调用方法,一切正常

trait A2 extends A {
    override def f( i: Int ) = super.f(i)
    override def g( i: Int ) = super.g(i)
    def h( i: Int ) = super.g(i)
}
val a2= new A2 {}
a2.f(2)
a2.g(4)
a2.h(6)

为什么两者之间有区别

val a1= new A {
    override def g( i: Int ) = super.g(i)
}

trait A2 extends A {
    override def g( i: Int ) = super.g(i)
}
val a2= new A2 {}

谢谢!

我会继续让我的评论成为答案。 这是一个错误。 它确实应该按照您期望的方式工作,但事实并非如此。

在 Java 中,受保护的成员可以被子类和定义成员的包访问,另一方面,在 Scala 中,成员仅对子类可见。

在您的情况下,代码可能是从实现 A 的类外部调用的(例如,从工作表)

如果要模拟 Java 行为,则可以使用表示法

protected[package_name] def g(i: Int) = println(i)

然后,方法g()将在包package_name内可见

您不必为了测试而与override玩游戏。你可以做这样的事情:

package com.foo.bar
trait MyTrait{
  def stuff(i: Int) = hidden(i) + 1
  protected[bar] hidden(i: Int): Int
}

然后在测试文件中

package com.foo.bar
class Testing extends Specification{
  "hidden" must{
    //some tests in here
   }

这是另一种说法,"hidden在包级别是可见的,因此该包中的任何内容都可以看到/测试它。

最新更新