Scala中的私有和受保护的构造函数


109

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

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

我错了吗?如果是这样,怎么做?


您可以拥有一个Scala单例(带有object关键字),并在该单例中将您的类定义为private,并具有用于构造对象的单例方法。
Paggas

@Paggas,不幸的是,当您返回一个标记为private的类的实例超出其作用域时,它将不会编译,即使从该方法的返回是在范围伴侣对象中。
Don Mackenzie

整个Scalaz源代码都相当丰富地完成了此操作。该概念也称为抽象代数数据类型。
托尼·莫里斯

Answers:


190

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

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

谢谢Aleksander,您能告诉我这是在一本Scala书中还是在语言规范中介绍的吗?抱歉,我还不能投票。
Don Mackenzie

我只是浏览了“ Programming Scala”对构造函数的解释(第92-95页),但我没有看到它的提法。我实际上是在旧的变更日志中找到了您问题的答案,但是我从未见过其他地方提到它。链接:scala-lang.org/node/43#2.4.0
Aleksander

18
第414页的“在Scala中编程”。Wampler的Programming Scala的第97页。Subramaniam编程Scala的第60页。我现在没有PDF的“ Scaling Scala”,无法查看。
Daniel C. Sobral

哦,我现在在第97页上看到它。谢谢。
Aleksander Kmetec

1
谢谢双方的进一步研究,我收到了Wampler的书,但仅在手机上阅读,显然还没有彻底阅读,但我发现它与Odersky的书相得益彰。
Don Mackenzie

64

Aleksander的答案是正确的,但是Scala编程提供了另一种替代方法:

sealed trait Foo {
 // interface
}

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

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

18
几年后突然冒出来说:我认为这对这个问题是一个很好的答案,但对这个问题却是一个不好的解决方案。如果将来有一些程序员使用Aleksander的代码,他会说“啊,主要的构造函数是私有的,而其他构造函数则不是。” 如果那个程序员要看Daniel的代码,他会说:“啊,他们使用Factory模式来补偿Scala无法将默认构造函数标记为私有。等等,Scala 可以将默认构造函数标记为私有!这是怎么回事?在这?!?” 换句话说,不良的WTF / LOC比。
马伏里奥

20
@马尔沃里奥我不太同意。这种模式不仅使主要构造函数私有,而且使实现私有,从而迫使用户使用接口(特征)。那有它自己的价值。至于某人因为他/她不懂语言而在想些什么-iff!引用肯尼·蒂尔顿的话,学习该死的语言
Daniel C. Sobral

7
应该在某处提到这种方法意味着不使用new关键字。
特拉维斯公园公园

1
这种方法的一个警告是,某些人仍然可以通过自己的实现实例化Foo。取决于控制构造的原因,这可以看作是优点还是缺点。
2013年

1
@aij是的,所以我做到了,这样就不再发生了。:)
Daniel C. Sobral
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.