@jducoeur, that’s a good observation. I hadn’t really considered the difference until now. I have two ways of creating an internal (non-leaf) Bdd
object, 1) the apply
methods of the Bdd
object, declared as follows:
object Bdd {
...
def apply(label: Int): Bdd = { ...}
def apply(label: Int, positive: Bdd, negative: Bdd): Bdd = { ...}
}
And 2) since BddNode
is a case class, then BddNode
may be called as a constructer. In fact the Bdd.apply
method calls BddNode
and memoizes the result.
I don’t 100% understand what it means (in terms of consequence) to have a private constructor (as this concept does not exist in CLOS, the Common Lisp Object System) but it does seem that I want Bdd.apply()
probably to be public and BddNode(...)
to be private. However, if I say, “I don’t want BddNode() to be callable elsewhere,” what does that restriction really mean? Does it also mean: I don’t want unit tests to be able to call it? Does it also mean: I want subclasses of BddNode
to be forced to copy/paste the code rather than calling it?
One part of my uncertainty is that one never knows how one might want to extend a program in the future. I may later want to create application specific subclasses of Bdd
, BddNode
, and BddLeaf
when trying to use binary decision diagrams and extend the behavior build into the base classes. I don’t understand the philosophy of “private” well enough to know how to write good code, without crippling future applications.
I admit that I don’t have the correct scala-think installed into my brain yet, but I don’t really think in terms of privacy, but in terms of protocol. The restriction, currently in the semantics of my program, is that BddNode(...)
should only be called in the context of something like what Bdd.apply(...)
sets up. Additionally I would like any application subclass of BddNode
to provide the analogous context when it creates an instance and BddNode
constructor is called by inheritance.