Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala case class private constructor but public apply method

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?

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) 
like image 818
Erik Avatar asked Nov 17 '13 12:11

Erik


People also ask

How do you make a case class private in a constructor?

To make the primary constructor private, insert the private keyword in between the class name and any parameters the constructor accepts: // a private no-args primary constructor class Order private { ... // a private one-arg primary constructor class Person private ( name : String ) { ...

Can a class have both private and public constructors?

We can't create public and private constructors simultaneously in a class, both without parameters. We can't instantiate the class with a private constructor. If we want to create an object of a class with private constructor then, we need to have public constructor along with it.

What can you not do with a class with private constructor?

If a class has one or more private constructor and no public constructor then other classes are not allowed to create instance of this class; this means you can neither create the object of the class nor can it be inherited by other classes.

Can scala case class have methods?

Case Classes You can construct them without using new. case classes automatically have equality and nice toString methods based on the constructor arguments. case classes can have methods just like normal classes.


2 Answers

Here's the technique to have a private constructor 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

like image 117
Farmor Avatar answered Oct 02 '22 03:10

Farmor


It seems the requested behavior (private constructor but public .apply) may be the way Scala 2.12 implements these.

I came to this from the opposing angle - would like a private case class constructor also block the .apply method. Reasons here: https://github.com/akauppi/case-class-gym

Interesting, how use cases differ.

like image 35
akauppi Avatar answered Oct 02 '22 04:10

akauppi