I was recently considering that sometimes several objects depend on each other (e.g. if they contain cyclic references) and therefore it would be useful to create them as part of one atomic operation that makes sure that, after construction, the new objects fulfil some collective constraint.
In order to do this one could have constructors that can create more than one object. The programmer would then put in a single constructor all the code ensuring that, once objects o1, …, on have been created, they satisfy all required constraints (e.g. all links between the new objects are already in place). I have made up the term collective constructors
myself because I have never heard of such a feature, but there might well exist an accepted name for this concept.
So, is there any programming language supporting this kind of constructors? If not, has the idea been tried out already?
10
This sounds like the Builder Pattern to me, which is a more complex form of a Factory. One Java example is a StringBuilder, which you use to build up a String, then call builder.toString()
when you want the immutable result. However, you can use the builder pattern to build more complex non-homogenous collections of objects. You could use friend
semantics in a builder to get access to private variables that would be considered immutable after the result object is created.
Functional languages might provide some inspiration. Scala, for example, has a mutable ListBuffer that can be used for the building stage, then converted to an immutable List.
Another possibly relevant concept is Freezable Objects, by which an object is considered mutable until a Freeze()
method is called on it. A builder could use the unfrozen objects, then freeze them before returning.
2
Ruby, Smalltalk, Self, Newspeak etc. don’t have constructors, they just have a naming convention for factory methods (e.g. new
in Ruby). Since they are just bog standard methods like any other method, they can do anything they want, including allocating and initializing as many objects as they want. The main problem is that such factory methods return, by convention, a single object that is an instance of the class the factory method was called on. I.e. when calling Foo.new
it is expected that you get back a single object which is an instance of Foo
. But, with sufficient documentation, you could return some structure (e.g. an Array
) of multiple new objects.
Example:
class Foo
def self.new
new_foo = super
new_bar = Bar.new
new_bar.foo = new_foo
new_foo.bar = new_bar
return new_foo, new_bar
end
attr_accessor :bar
end
class Bar
attr_accessor :foo
end
foo, bar = Foo.new
In ECMAScript, constructors are just regular procedures, or rather, any procedure can be used as a constructor just by sticking the new
keyword in front of it. Again, since they are just regular procedures, they can do anything they want.
(e.g. if they contain cyclic references) […] In order to do this one could have constructors that can create more than one object. The programmer would then put in a single constructor all the code ensuring that, once objects o1, …, on have been created,
Cyclic dependencies between the objects? Then the answer is “don’t use (just) a constructor”, because cyclic method calls don’t make any sense. Instead, this is a classic scenario for some Factory methods.
Here’s an example (in PHP) which is sort of silly but illustrates the general idea: You cannot create a Sprocket
without an associated Widget
, and vice-versa. Each object has a reference to the other when it becomes available.
class Widget {
protected $sprocket = null;
public function getSprocket(){ return $this->sprocket; }
protected function __construct(){
// Constructor cannot be called from outside, not public
// Initialize self, to a limited degree
}
public static function create(Sprocket $partner=null){
$me = new Widget(); // Can call constructor from same class
// Here we can make all sorts of changes and additions and other
// objects, wiring them all together, before revealing the result
// to the outside world.
if($partner !== null){
$me->sprocket = $partner;
}else{
$me->sprocket = Sprocket::create($me);
}
return $me;
}
}
/*
* Practically identical to Widget, just with some renaming
*/
class Sprocket {
protected $widget = null;
public function getWidget(){ return $this->widget; }
protected function __construct(){ }
public static function create(Widget $partner=null){
$me = new Sprocket();
if($partner !== null){
$me->widget = $partner;
}else{
$me->widget = Widget::create($me);
}
return $me;
}
}
/*
$mw = new Widget(); // NOT ALLOWED! Constructor not public
*/
$w = Widget::create(); // OK to call
$s = $w->getSprocket();
$w2 = $s->getWidget();
assert($w == $w2);
If I had to do this in PHP 5.2 in real life, I’d simply just leave the constructors public, and tell people not to use them. Instead I’d have a makeWidgetWithSprocket()
function. If the language was Java, I’d use its package-level visibility controls to further prevent mistakes.
Additional reading:
- If you want to pass lots of options and settings to
create()
, consider the Builder pattern. - If you find yourself needing a lot of flexibility to rewire things in different ways, look at Inversion of Control frameworks, which commonly (but not always) use dependency injection to connect objects together “from the outside”.