【问题标题】:how to inherit a protected/private of an abstract class in Scala如何在Scala中继承抽象类的受保护/私有
【发布时间】:2017-11-28 13:45:29
【问题描述】:

我有一个抽象类,其中包含一个对象和一个代表二叉树的具体子类,用于按字典顺序对一组字符串进行排序。

abstract class StringSet {
  def incl(x:String):StringSet
  def contains(x:String):Boolean
  def union(that:StringSet):StringSet

  def biggest:String // this is my new method
  def bigIter(acc:String):String //this is my new helper method
}
object Empty extends StringSet {
  override def toString: String = "."
  def incl(x: String): StringSet = new NonEmpty(x, Empty, Empty)
  def contains(x: String): Boolean = false
  def union(that:StringSet):StringSet = that

  def biggest:String = throw new java.util.NoSuchElementException("...")
  def bigIter(acc:String):String = acc
}
class NonEmpty(elem:String, left:StringSet, right:StringSet) extends StringSet {
  def incl(x: String): StringSet = {
    if (x < elem) new NonEmpty(elem, left incl x, right)
    else if (x > elem) new NonEmpty(elem, left, right incl x)
    else this
  }
  def contains(x: String): Boolean = {
    if (x < elem) left contains x
    else if (x > elem) right contains x
    else true
  }
  def union(that:StringSet):StringSet = ((left union right) union that) incl elem

  def biggest:String =  bigIter(elem)
  def bigIter(acc:String):String = 
    if (elem < acc) left union right bigIter acc
    else left union right bigIter elem
}

我想实现一个获取最大字符串的方法,只以“功能方式”使用为该类创建的方法。我使用了没有返回字符串的参数的“最大”方法,该方法调用了另一个方法“bigIter”,该方法递归地调用自身,直到它遍历所有树。

我的想法奏效了,但我想隐藏 bigIter 实现,以便用户只能看到“Biggest”方法。我在抽象类和具体类上为 bigIter 使用了 protected 和 private,但它不起作用。我尝试在抽象类中使用带有 bigIter 方法的私有方法,但无法继承超类的私有方法。我也尝试过protected,将它与超类和子类一起使用,得到以下错误

错误:(50, 39) 类 StringSet 中的方法 bigiter 无法访问 A$A3.this.StringSet 不允许访问受保护的方法 bigiter 因为前缀类型 A$A3.this.StringSet 不符合类 进行访问的 A$A3 类中的 NonEmpty if (elem

关于如何实现这一点的任何想法?

注意: 1. 在 Empty 上调用最大应该返回一个错误,所以这就是我从具体类中调用“bigIter”的原因。
2. 这是我正在做的一门课程,所以这个想法不是使用高阶列表函数。

【问题讨论】:

  • “我在抽象类和具体类上为 bigIter 使用了 protected 和 private,但它不起作用。” 什么不起作用?错误是什么?
  • 如果我正确理解了您对“最大”的定义,您不应该只需要查看right 子集吗?
  • private 事物不会被继承。 protected 有什么不好的地方?
  • @Yuval Itzchakov 我用你的观察更新了这个问题。谢谢
  • @Jasper-M 我也用过protected。我用我得到的输出更新了这个问题。谢谢

标签: scala class inheritance functional-programming abstract-class


【解决方案1】:

SI-9890 解释了为什么当您尝试访问派生类型实例中超类型上的方法时编译器会不高兴。 The specification restricts this:

受保护的标识符x 可以用作选择中的成员名称 r.x 仅适用于以下条件之一:

  • 访问在定义成员的模板内,或者,如果给定条件 C,则在包 C,或类 C,或其配套模块内,或
  • r 是 this 和 super 的保留字之一,或者
  • r's 类型符合包含访问权限的类的类型实例。

最后一个项目符号基本上表示r,在你的情况下是StringSet,必须是NonEmpty类型。

要解决这个问题,您可以将 StringSet 的所有实现放在同一个包下,并在 bigIter 上设置 protected[package]。例如,假设你的包名是foo,你可以这样做:

protected[foo] def bigIter(acc: String): String 

现在它可以编译了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 2010-10-26
    • 2013-12-14
    相关资源
    最近更新 更多