2011-11-28 21 views
1

的亚型。虽然这种按预期工作:隐私内部类和可访问性,从我在使用的内部类,方法和构造私人注释困难外型

trait A { 
    protected def lala =() 
} 

trait B extends A { 
    lala 
} 

下列不:

trait A { 
    class Lala protected() 
} 

trait B extends A { 
    new Lala 
} 

无论是做这个的:

trait A { 
    class Lala private[A]() 
} 

trait B extends A { 
    new Lala 
} 

唯一的办法解决是这样的:

object Screwed { 
    trait A { 
    class Lala private[Screwed]() 
    } 

    trait B extends A { 
    new Lala 
    } 
} 

是否真的斯卡拉这里失败Ť o提供一个清晰的机制,还是我错过了什么?我的猜测应该是private[this.type],但scalac根本不想吞下去......

回答

6

好,

trait A { 
    class Lala protected() 
    new Lala 
} 

没有任何编译。该错误消息似乎很合理:

error: constructor Lala in class Lala cannot be accessed in trait A 
Access to protected constructor Lala not permitted because 
enclosing class trait A in object $iw is not a subclass of 
class Lala in trait A where target is defined 

保护访问意味着你只能从类或子类访问构造函数。你试图从封闭的特质中调用它。你可以做的一件事是这样的:

trait B extends A { 
    class Gaga extends Lala 
    new Gaga 
} 

我不希望你的第三个例子编译,出于类似的原因。

还要注意一个受保护的构造和protected class之间的区别。因此,例如:

trait A { 
    protected class P 
    class U // unprotected 
} 

class B extends A { 
    new P // OK 
    new U // OK 
} 

val b = new B 
new b.P // error 
new b.U // OK 
+0

事实上'受保护的类'是适合我的解决方案 –

0

受保护的人应该肯定能工作,你会得到什么错误?对于私人用户来说,你定义的范围控制着他们的可见性(所以在特质A中,如果你给出了A的可见性,它在B中显然是不可见的)。在最后一个例子中,你已经将范围赋予了Screwed,因此Screwed中的任何内容都能够看到私有类。顺便说一句,我喜欢写访问修饰符的第一件事就是在一个代码行,以便方便阅读

您使用的是什么版本的斯卡拉和你所说的“不工作”是什么意思?

HTH!

+0

'的错误:在类的构造函数啦啦啦啦不能特质B'访问。作为路易指出,'protected'指Lala'的'范围,而不是'A',并且似乎没有成为在__A知名度或A__亚型的任何可能的范围。我原本以为我会从'private [A]'或至少''protected [A]''得到这个。 –

+0

@Sciss也许你需要一个'protected class'?我已经更新了我的答案。 –

+0

感谢Luigi,我认为返回一个'protected'内部类的实例会产生'Lala''逃避'它的上下文的问题,但是你是对的,这是有效的! –

1

这也适用于所期望的可见性(Lala只能从AA亚型实例化)。

trait A { 
    class Lala private[A]() 
    protected def newLala = new Lala 
} 

trait B extends A { 
    newLala 
} 

我不知道什么是像protected[A]目的,如果它不能在这种情况下工作。