Reputation: 281
I'm not really sure what to call this, because "static constructor" seems to convey the concept of static initializer blocks, but my question has to do with style.
Let's say I have a class Weapon that has your standard constructors for initializing a weapon's stats. This works fine, but sometimes I want to randomly generate a weapon. I could create a static method called FromRandom which creates a new Weapon with random stats and returns it. That way I could do something like this:
Weapon randWeapon = Weapon.FromRandom();
What's the consensus on this? Is this acceptable code?
Upvotes: 2
Views: 6758
Reputation: 17713
Generally speaking, this is good and gives you some grace to the code. But I'd recommend this only for factory classes. Why? Let's consider your example
Weapon weapon = Weapon.create();
If I have a subclass of Weapon
, e.g. Pistol
with a static method similar to the previous in which you can do pass a param (bullet size for instance), then you may do
Weapon randWeapon = Pistol.create("9mm");
but you may do by mistake
Weapon randWeapon = Pistol.create();
which will not create a Pistol
, but an instance of the parent class. Is this desired? Not sure. Can it be worse? Well, just think about the possibility to define create
method in class Pistol
as
public static Pistol create(String ... args){...}
Scaring, isn't it?
So, if one does not want to create a factory class, the solution would be to make the class final
, but I generally advice people not to create final classes (think about issues with mocking).
Upvotes: 0
Reputation: 41209
Giving a class static methods that give you more control and gracefulness by returning instances of the class they are in is perfectly acceptable code. This is actually called the factory method pattern and is used quite often when you greater control when an instance of a class is created.
Basically, you have the static method call one of the class constructors, do whatever it needs to do in terms of logging the creation of the object, adding it to a collection, performing further operations on it, etc., and then return the created object, so the method ends up being used like a normal constructor. :D
Upvotes: 7
Reputation: 26040
This is (similar, in a way) to a well known design pattern, known as the Abstract Factory Pattern, see: http://en.wikipedia.org/wiki/Abstract_factory_pattern
Upvotes: 1
Reputation: 284786
I would prefer having multiple constructors, with parameters determining how to create the object. If there's only two options, use a boolean (you can keep the default version and chain it). If there are many, use an enum parameter.
However, I wouldn't necessarily consider your code wrong. Guava uses a similar style (see Lists
). However, note that it returns instances of another class (List
), and itself has no constructor.
Upvotes: 2