scala Scala案例类私有构造函数但公共应用方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20030826/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scala case class private constructor but public apply method
提问by Erik
If I have the following case class with a private constructor and I can not access the apply-method in the companion object.
如果我有以下带有私有构造函数的案例类,并且我无法访问伴随对象中的应用方法。
case class Meter private (m: Int)
val m = Meter(10) // constructor Meter in class Meter cannot be accessed...
Is there a way to use a case class with a private constructor but keep the generated apply-method in the companion public?
有没有办法使用带有私有构造函数的 case 类,但将生成的 apply-method 保留在公共公共中?
I am aware that there is no difference (in my example) between the two options:
我知道这两个选项之间没有区别(在我的示例中):
val m1 = new Meter(10)
val m2 = Meter(10)
but I want to forbid the first option.
但我想禁止第一个选项。
-- edit --
- 编辑 -
Surprisingly the following works (but is not really what i want):
令人惊讶的是以下工作(但不是我真正想要的):
val x = Meter
val m3 = x(10) // m3 : Meter = Meter(10)
回答by Farmor
Here's the technique to have a privateconstructor and a public apply method.
这是拥有私有构造函数和公共应用方法的技术。
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)
}
Background information private-and-protected-constructor-in-scala
回答by akauppi
It seems the requested behavior (private constructor but public .apply) may be the way Scala 2.12 implements these.
似乎请求的行为(私有构造函数但 public .apply)可能是 Scala 2.12 实现这些的方式。
I came to this from the opposing angle - would like a private case class constructor also block the .applymethod. Reasons here: https://github.com/akauppi/case-class-gym
我从相反的角度来到这里 - 想要一个私有案例类构造函数也阻止该.apply方法。原因在这里:https: //github.com/akauppi/case-class-gym
Interesting, how use cases differ.
有趣的是,用例有何不同。
回答by Yuriy
It is possible with some implicit tricks:
有一些隐含的技巧是可能的:
// first case
case class Meter[T] private (m: T)(implicit ev: T =:= Int)
object Meter {
def apply(m: Int) = new Meter(m + 5)
}
created some another constructor (and apply method signature) but guaranty that parameter can be only Int.
创建了另一个构造函数(并应用方法签名),但保证该参数只能是Int.
And after you have case class with case class features (with pattern matching, hashcode & equals) exclude default constructor:
在您拥有具有案例类功能的案例类(具有模式匹配、哈希码和等于)之后,排除默认构造函数:
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 with type tagging (naive implementation):
或带有类型标记(幼稚的实现):
trait Private
case class Meter private (m: Integer with Private)
object Meter {
def apply(m: Int) = new Meter((m + 5).asInstanceOf[Integer with Private])
}
It works as expected:
它按预期工作:
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)
Some possible issues with primitive types and type tags described here
此处描述的原始类型和类型标记的一些可能问题

