Search code examples
scalaaccess-modifierscase-classcompanion-objectprivate-constructor

Why is private constructor still visible in case class?


I want to hide constructor in one class along with its fields and only create instances using a companion object, but I can't achieve that. I have scala 2.13.3 and it's based on java 8. Here is a code sample:

A.scala

package X

object A {
  def apply(x: Int): A = A(Seq(x))
}

case class A private(private val s: Seq[Int])

B.scala

package Y

import X.A

class B {
  val b = A(Seq.empty)
}

And although I wanted to make only apply(x:Int) visible this code compiles so the private constructor is also visible. How can I change this code to work as I expected?


Solution

  • Make the method A.apply(Seq[Int]) private too

    A.scala

    package X
    
    object A {
      def apply(x: Int): A = A(Seq(x))
      private def apply(s: Seq[Int]): A = new A(s) // make explicit and private instead of auto-generated and public
    }
    
    case class A private(private val s: Seq[Int])
    

    B.scala

    package Y
    
    import X.A
    
    class B {
      //val b = A(Seq.empty) // doesn't compile
    }
    

    Here the line val b = A(Seq.empty) produces error

    Error: polymorphic expression cannot be instantiated to expected type;
     found   : [A]Seq[A]
     required: Int
    

    i.e. the method A.apply(Seq[Int]) is not visible from B.