2014-02-10 49 views
3

我想實例化一個特徵並覆蓋受保護的函數g,使其可訪問(函數f用於測試)。scala覆蓋受保護的成員函數

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 

但是,當我定義擴展一個和重寫方法˚F性狀A2,創建它的一個實例,並調用方法,一切工作正常

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 {} 

謝謝!

+0

簡答:這是一個錯誤。 HTTPS://issues.scala-lang。組織/瀏覽/ SI-1352 –

回答

1

在Java保護的成員可以通過Scala中的子類和成員定義的包訪問,另一方面,成員只對子類可見。

在你的情況下,代碼可能是由一類的外部調用的實現(例如,從工作表)

如果要模擬Java的行爲,那麼你可以使用符號

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

然後,方法g()將在包內可見package_name

+0

我的目的是通過覆蓋它來訪問受保護的方法 - 無論這個方法是否合理 - 我必須考慮這個方法 – user3293103

1

您不必與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,在包裝水平可見的,所以這個包內的任何東西都可以看到/測試它。「

+0

感謝提示,我會試一試。我是scala的新手,當遇到問題時,我寫了一些簡單的代碼。最初我想覆蓋_scala.collection.mutable.Publisher_中的_publish_ – user3293103

2

我會繼續前進,並且讓我的評論成爲答案。 It's a bug。它確實應該按照你期望的方式工作,但事實並非如此。