312748 (4) [Avatar] Offline
In the book, we are given an example of a smart constructor like the following:

final case class CheckingAccount private(no: String, name: String, dateOfOpen: Option[Date], dateOfClose: Option[Date], balance: Balance) extends Account

object Account {
  def checkingAccount(no: String, name: String, openDate: Option[Date], closeDate: Option[Date], balance: Balance): Try[Account] = {
    closeDateCheck(openDate, closeDate).map { d =>
    CheckingAccount(no, name, Some(d._1), d._2, balance)

Here the case class is final in order to prevent anyone from extending it and thus constructing their own unsafe instances of CheckingAccount. We also make the constructor private in order to prevent instantiation with the new keyword. What this fails to address, however, is that you can still create an unsafe instance using the apply() method of the companion object. How do we address this issue? Originally I was thinking of overriding the apply method to make it private but this results in a compiler error because now the apply method is defined twice (once by the you and once by the compiler for the cass class).

The example in the online repo for Chapter 3 (https://github.com/debasishg/frdomain/blob/master/src/main/scala/frdomain/ch3/smartconstructor/Account.scala) defines the 'copy' and 'apply' methods "to ensure that the user cannot use" them but I really don't see how that is because those methods are still available in the companion object.

Is there a better way of achieving a safer smartconstructor?