プライベートコンストラクターを持つ次のケースクラスがあり、コンパニオンオブジェクトのapply-methodにアクセスできない場合。
case class Meter private (m: Int)
val m = Meter(10) // constructor Meter in class Meter cannot be accessed...
プライベートコンストラクターでケースクラスを使用する方法はありますが、生成された適用メソッドをコンパニオンパブリックに保持しますか?
私の例では、2つのオプションの間に違いがないことを認識しています。
val m1 = new Meter(10)
val m2 = Meter(10)
しかし、私は最初のオプションを禁止したいと思います。
-編集-
驚くべきことに、次の作品(しかし、私が本当に望んでいるものではありません):
val x = Meter
val m3 = x(10) // m3 : Meter = Meter(10)
privateコンストラクターと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)
}
要求された動作(プライベートコンストラクターですが、パブリック.apply
)は、Scala 2.12がこれらを実装する方法である可能性があります。
私は反対の角度からこれに来ました-プライベートケースクラスコンストラクターも.apply
メソッドをブロックしたいと思います。ここに理由: https://github.com/akauppi/case-class-gym
興味深いのは、ユースケースの違いです。
いくつかの暗黙のトリックで可能です:
// first case
case class Meter[T] private (m: T)(implicit ev: T =:= Int)
object Meter {
def apply(m: Int) = new Meter(m + 5)
}
いくつかの別のコンストラクター(および適用メソッドシグネチャ)を作成しましたが、そのパラメーターはInt
のみであることが保証されています。
そして、ケースクラスの機能を持つケースクラス(のパターンマッチング、ハッシュコード&equalsを含む)を作成したら、デフォルトのコンストラクタを除外します。
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)
またはタイプのタグ付け(単純な実装)を使用:
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