如果我有以下具有私有构造函数的case类,并且我无法访问companion对象中的apply-method。
case class Meter private (m: Int)
val m = Meter(10) // constructor Meter in class Meter cannot be accessed...
有没有办法将case类与私有构造函数一起使用,但是在公开的伴随文件中保留生成的apply-method?
我知道两个选项之间没有区别(在我的例子中):
val m1 = new Meter(10)
val m2 = Meter(10)
但我想禁止第一个选项。
- 编辑 -
令人惊讶的是以下作品(但实际上并不是我想要的):
val x = Meter
val m3 = x(10) // m3 : Meter = Meter(10)
答案 0 :(得分:41)
这是使用私有构造函数和公开应用方法的技术。
trait Meter {
def m: Int
}
object Meter {
def apply(m: Int): Meter = { MeterImpl(m) }
private case class MeterImpl(m: Int) extends Meter { println(m) }
}
object Application extends App {
val m1 = new Meter(10) // Forbidden
val m2 = Meter(10)
}
答案 1 :(得分:0)
可能有一些隐含的技巧:
// first case
case class Meter[T] private (m: T)(implicit ev: T =:= Int)
object Meter {
def apply(m: Int) = new Meter(m + 5)
}
创建了另一个构造函数(并应用方法签名),但保证该参数只能是Int
。
在您拥有案例类功能的案例类(使用模式匹配,哈希码和等于)之后,排除默认构造函数:
scala> val m = Meter(10)
m: Metter[Int] = Meter(15)
scala> val m = new Meter(10)
<console>:9: error: constructor Meter in class Meter cannot be accessed in object $iw
val m = new Meter(10)
OR与类型标记(天真实现):
trait Private
case class Meter private (m: Integer with Private)
object Meter {
def apply(m: Int) = new Meter((m + 5).asInstanceOf[Integer with Private])
}
按预期工作:
val x = new Meter(10)
<console>:11: error: constructor Meter in class Meter cannot be accessed in object $iw
new Meter(10)
^
val x = Meter(10)
x: Meter = Meter(15)
原始类型和类型标记的一些可能问题描述为here
答案 2 :(得分:0)
似乎请求的行为(私有构造函数但公共.apply
)可能是Scala 2.12实现这些行为的方式。
我是从相反的角度来看这个问题的-就像一个私人案例类构造函数也阻塞了.apply
方法。原因如下:https://github.com/akauppi/case-class-gym
有趣的是,用例有何不同。