允许组合时在Scala中声明受保护方法的惯用方式?

Posted

技术标签:

【中文标题】允许组合时在Scala中声明受保护方法的惯用方式?【英文标题】:idiomatic way to declare protected method in Scala when allowing for composition? 【发布时间】:2014-01-23 05:17:16 【问题描述】:

我在包foo 中有一个抽象类(在这种特殊情况下,是一个特征),可以由各种子类实现,我想创建一个正交子类以在更具体的包bar 中使用添加特定于包的信息。似乎最好的方法是通过组合(包装)而不是继承,因为否则我必须声明每个 foo-package 子类的特定于包的版本。但这会导致需要转发的受保护成员出现问题:

package foo 
  trait Foo 
    protected def bar: Int
  


package bar 
  import foo.Foo
  class Baz
  class WrapFoo(wrapped: Foo) extends Baz with Foo 
    protected def bar = wrapped.bar
  

这会导致错误:

~/test/scala 14:54 152272% scalac testprotected.scala
testprotected.scala:11: error: method bar in trait Foo cannot be accessed in foo.Foo
 Access to protected method bar not permitted because
 prefix type foo.Foo does not conform to
 class WrapFoo in package bar where the access take place
    protected def bar = wrapped.bar
                                ^
one error found

尽管WrapFooFoo 的子类,但scala 不喜欢调用wrapped.bar。我猜这是因为WrapFoo 类型的对象不是wrapped 的子对象。

问题是:在bar 上声明保护的惯用方式是什么,而不是简单地公开?函数bar 旨在被Foo 中的其他函数调用,而不是公开调用。 Scala 有一个富有表现力的保护系统,但我不太了解它。这可能吗?

【问题讨论】:

【参考方案1】:

将这两种类型放在一个公共包中,它可以位于包层次结构中的任何位置,而不必是直接父级。

然后您可以使用protected[packagename]private[packagename] 来选择性地控制访问。

【讨论】:

这是唯一的方法吗?就我而言,这具有使整个程序可以访问代码的效果。包布局早已确立,仅仅为此而重新调整会弄乱许多其他事情。

以上是关于允许组合时在Scala中声明受保护方法的惯用方式?的主要内容,如果未能解决你的问题,请参考以下文章

Scala:如何使子类(在其他实例上)可以访问受保护的方法?

“受保护的朋友”和“私人保护”有啥区别?

Scala 类定义中受保护关键字的含义是啥?

Scala 中其他实例的受保护成员

为啥 Java 允许增加子类中受保护方法的可见性?

派生类 C++ 中基类受保护成员的访问声明为公共的