【问题标题】:Private and protected constructor in ScalaScala中的私有和受保护构造函数
【发布时间】:2010-12-16 09:02:21
【问题描述】:

我一直对在 Scala 中没有显式主构造函数的影响感到好奇,只有类主体的内容。

特别是,我怀疑私有或受保护的构造函数模式,即通过伴随对象或另一个类或对象的方法控制构造可能没有明显的实现。

我错了吗?如果有,是怎么做的?

【问题讨论】:

  • 您可以有一个 Scala 单例(即带有 object 关键字),并在该单例中将您的类定义为私有,并使用该单例的方法来构造您的对象。
  • @Paggas,不幸的是,当您在其范围之外返回标记为私有的类的实例时,即使从其范围内伴随对象的方法返回,它也不会编译。
  • 这在整个 Scalaz 源代码中被大量使用。该概念也称为抽象代数数据类型。

标签: scala


【解决方案1】:

您可以通过在类名和参数列表之间插入适当的关键字来将默认构造函数声明为私有/受保护,如下所示:

class Foo private () { 
  /* class body goes here... */
}

【讨论】:

  • 感谢 Aleksander,您能否告诉我这是否出现在 scala 书籍之一或语言规范中?抱歉,我还不能投票。
  • 我只是浏览了“Scala 编程”对构造函数的解释(第 92-95 页),但我没有看到那里提到它。实际上,我在旧的变更日志中找到了您问题的答案,但我之前从未在其他任何地方看到过它。链接:scala-lang.org/node/43#2.4.0
  • “Scala 编程”第 414 页。 Wampler 的 Programming Scala 第 97 页。 Subramaniam 的 Programming Scala 第 60 页。我现在手上没有《Beginning Scala》的 PDF 来查看它。
  • 哦,我现在在第 97 页上看到了。谢谢。
  • 感谢两位的进一步研究,我得到了 Wampler 的书,但只是在手机上,显然没有仔细阅读,但我发现它与 Odersky 的书相得益彰。
【解决方案2】:

Aleksander 的答案是正确的,但Programming in Scala 提供了另一种选择:

sealed trait Foo {
 // interface
}

object Foo {
  def apply(...): Foo = // public constructor

  private class FooImpl(...) extends Foo { ... } // real class
}

【讨论】:

  • 多年后突然说:我认为这是对问题的一个很好的答案,但对问题的解决方案却很糟糕。如果某个未来的程序员对 Aleksander 的代码感兴趣,他会说“啊,主构造函数是私有的,但其他构造函数不是。”如果那个程序员看到 Daniel 的代码,他会说,“啊,他们正在使用工厂模式来弥补 Scala 无法将默认构造函数标记为私有的。等等,Scala 的 can 标记默认构造函数构造函数是私有的!这是怎么回事?!?”换句话说,糟糕的 WTF/LOC 比率。
  • @Malvolio 我不太同意。这种模式不仅使主构造函数私有,而且使实现,迫使用户使用接口(特征)。这有它自己的价值。至于有人因为他/她不懂语言而想什么——piffle!引用肯尼蒂尔顿的话,learn the damn language!
  • 应该在某处提到这种方法意味着不使用new关键字。
  • 这种方法的一个警告是有人仍然可以通过他们自己的实现来实例化 Foo。根据控制施工的原因,这可以被视为优势或劣势。
  • @aij 是的,所以我做到了,这样就不会再发生了。 :)
猜你喜欢
  • 1970-01-01
  • 2019-08-24
  • 2016-06-19
  • 2012-12-24
  • 2016-04-07
  • 2011-03-15
  • 2019-02-21
  • 1970-01-01
  • 2016-05-22
相关资源
最近更新 更多