【问题标题】:Restrict Construction of Scala Class限制Scala类的构造
【发布时间】:2015-09-25 01:41:47
【问题描述】:

给定:

class Foo(x: Int) {}

object Foo {
  def apply(x: Int) = new Foo(x)
}

除了将Foo 的构造函数标记为private 之外,如何在调用new Foo(...) 时显示警告或编译时失败?

换句话说,我想将Foo 的构造(通过编译时警告或错误)限制为Foo.apply

这可能吗?

【问题讨论】:

  • 为什么“除了将 Foo 的构造函数标记为私有”?那个解决方案有什么问题?
  • 这就是将构造函数标记为私有的原因 for
  • 值类忽略私有,不是吗?
  • @KevinMeredith,没有。检查我的答案的更新,并点击其中的链接了解更多详情。

标签: scala


【解决方案1】:

在 scala 中,有两种惯用的方法来实现这一点。

  1. 类和伴随对象私有的构造函数。

工厂可以访问构造函数,而其他任何人都没有:

class Foo private[Foo](val x: Int)

object Foo {
  def apply(x:Int) = new Foo(x)
}

val foo = new Foo(1)  // cannot compile
val foo1 = Foo(1) //compiles fine
  1. 密封的抽象类。

在 scala 中 sealed 类只能在它定义的同一个源文件中扩展。 我建议在对象的 apply 方法中创建 Foo sealed abstract class 并返回 Foo 的匿名子节点。

sealed abstract class Foo(val x:Int)

object Foo {
  def apply(x:Int):Foo = new Foo(x) {}
}

在这种情况下,Foo 只能在定义它的文件之外的任何地方创建。

UPD:其实这个问题已经是discussed on stackoverflow了。

UPD2:添加了两种方法的简要概述。

【讨论】:

  • 但是不能实例化abstract class
  • @KevinMeredith,这就是重点。在object Foo 中,您可以创建扩展Foo 的匿名类的对象(这就是为什么new Foo 之后有花括号),而在其他文件中您不能这样做,因为Foo 是抽象和密封的,这意味着您不能直接创建它,也不能扩展它以实例化它的子节点。
猜你喜欢
  • 2011-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-28
  • 1970-01-01
  • 2013-03-16
  • 2013-03-04
  • 2020-10-07
相关资源
最近更新 更多