I don't get it... I want to specify an interface that says any class which implements it must also implement a specific constructor (used for dynamically specifying the class at run time). Why on Earth can I not do this with Java? I cannot think of any possible reason and it's just a pain. -KristofferLawson
Someone else also does not like it: http://zoom.z3950.org/bind/java/comment/constructor.html
At the risk of stating the obvious, I think you need a FactoryMethod. Maybe even the AbstractFactory pattern. See DesignPatternsBook.
Generally, if you find yourself saying, "I need a virtual constructor.", this tells you that you probably need to use some FactoryPattern.
Indeed, I happen to have done the very thing this week: I was thinking of using Reflection to create instances of various similar classes, but decided to put a FactoryMethod in an interface, and create AbstractFactory instances to do object construction, through the well-defined type-safe interface FactoryMethod.
Could someone please explain how a "constructor for an interface" would ever work? Constructors are called by new-expressions. This is often the only place where the concrete type of the new object is specified. If you "new" an interface, what type of object should be constructed? That cannot possibly work!
In fact, the misconception is so old, it was a FAQ for TurboPascal
in the early 90s... To specify the concrete type "out of band", you need reflection. But then there's nothing amiss here, you can already find the constructor if it exists.
To specify the concrete type "out of band", you need reflection.
Give that man a CIGAR!.
Another example that demonstrates NoRealJavaMetaModel
Of course, there is NoRealJavaMetaModel
and yes, Factory etc. are the usual solutions. But that doesn't mean, that Java couldn't have added one more kink to its specification by allowing these constructor 'requirements'. The root poster was well aware, that he could call the constructor by reflection on the class. He just wanted to ensure, that every class
of a certain kind had this constructor (that the class is appropriate can
be checked in java). -- .gz
Exactly, this is what I wished. Something similar can be done with factories, but why should I have to? Why can I not use the most natural method for defining the kind of constructor I want all classes to implement, if they agree to a particular interface? In fact, perhaps this could be generalized to the problem JavaConstructorsAreNotMethods?
. This leads to another problem when wanting to use the constructor of the superclass. It doesn't 'just work'. One has to create a constructor that calls super(). This is particularly annoying with exceptions which often tend to not do or add anything to their superclass but are only used as a form of classification. -- KristofferLawson
I'm repeating my question: How would this work?
The current state of affairs is that a factory function that implements "Construct me an instance of this Class!" does the following (assume that this "this Class" is given by it's name or as an instance of Class):
- (optional) get an instance of Class using reflection
- check if the class implements the appropriate interface
- try to get the appropriate constructor
- massage the parameters into an array
- invoke it
- cast the result to the interface type and return it
If an interface could specify a constructor, nothing would be different. Getting the constructor could no longer fail, instead the function fails on step earlier, which is no significant difference at all. A static type check is impossible both ways.
Now assume a class implements an interface and forgets to implement the (informally) specified constructor. What would break? Basically nothing. Since constructors are never called on existing objects, there's no visible difference. LSP is not violated. The only thing that breaks is the factory function. But who cares? If these objects get constructed some other way, they are perfectly fine.
So what is it you want? A way to document your desire for that constructor? It's already there, they call it a "comment".
The problem is again, that Java (as many other OO languages too) mixes class methods (constructors and static methods) with object methods (normal 'virtual' methods) in one definition/scope. Using parameterized constructors makes the matters worse than necessary. If you look at the VM, you can clearly see, that constructor invocation is a two-step process: 1) call "new" with the class-name and 2) call an "<init>" method with the appropriate parameters. IMHO these two steps should not be merged inseparably. I think it would fully fit your purpose if you could specify the required init-methods (which obviously can be inherited and are present in the VM anyway) leaving the empty constructor as a 'static' class method. Anyway, this is idle wishing, as Java IsAsItIs?
. -- GunnarZarncke
The Objective-C language makes this explicit - there are no special constructor methods, and alloc: and init: are two different methods. Many of the core classes include factory methods having "With" in the name that do the alloc and init for you.
NSString *empty = [[NSString] alloc] init]; // an empty (immutable) string -- not very useful
NSString *text = [NSString stringWithCString: "Hello, World!"];
Why don't you put an init() method in your interface? -- PhilippeDetournay
I'm not sure how the init method works in Java. It would require certain parameters. Is it called by new? If not and I would have to call it separately as a normal method then that kind of defeats the purpose of having constructors, which should be able to handle that. As mentioned above, the Objective C model would work fine. Also, in the XoTclExtension
constructors are just normal instance methods (an 'init' method) which gets called when instantiation of the class object is made. I believe the Java model is weaker than either of these solutions. -- KristofferLawson
It is perfectly possible to define a meta-interface for each Java interface desired, and connect the meta-interfaces together in a parallel graph to the interfaces. For convenience, these can all root in some interface "IObject" or something similar, and this interface provides a "klass" or "clazz" method. In such an approach, every instance of every object has a klass/clazz. You'll want the clazz and metaclazz graphs to root in a common ancestor, like - just to pick a name at random - IBehavior. This interface can specify a method called "create()", returning an IObject. When an instance of SomeKlass?
is needed, accomplish it by invoking "create" on an instance of a Klass implementing SomeKlass?
aSomeKlass = SomeKlass?.create();
Any klass/clazz can provide versions of create() that take various arguments. Classes that implement these interfaces invoke the new operator to actually create their class.
It works fine, I've built a subsystem called "clazzy" that works this way. There is hair, by the way, and without tools to help this will result in astonishing code-bloat -- but it's java, so that's to be expected.
. It was used for creating the nodes of large dynamic DocumentGraph?
s. Each node had a small inner class Builder (that's how we called it, it was really just a minimal class to create the corresponding node, there were more then one methods, but basically a create() with some parameters like root node, parent and relative position in parent node). For convenience a builder was returned by a static getBuilder() method in the node class, which was looked up in some cases by reflection (i.e. when node types were specified dynamically in the source document). Otherwise the builders were stored and used by document parsers and sometimes within the DocumentGraph?
nodes when these could change dynamically.
These were no real MetaClass
es and keeping them as inner classes reduced Class
Sure, there are various ways to get round this, but why should we have to? That is the point. I can't see any benefit in the way Java has decided to do it. -- KristofferLawson
For me, this is a manifestation of NoRealJavaMetaModel. I don't see how interfaces could specify constructors other than through a meta-model. Whether you call it a "Class", "Klass", "Clazz", or "Factory", it seems to me that you need an OBJECT, different from the instances you want to create, to which you send messages. It isn't just constructors - you can't specify ANY static methods in a Java Interface. Yet the ONLY way to provide "class" behavior in out-of-the-box Java is with static methods. Thus, you really DO need a real meta-model. -- TomStambaugh
It's really quite simple. I have some applications which dynamically load classes and create instances of them. I want to provide a formal way to say 'all these classes should have a constructor like this' and have the compiler really check that is so for any classes specified to conform to my interface. Sure, a runtime error occurs in any case if they don't comply (the suitable Constructor could not be found or whatever), but seeing as we have formality for all kinds of other stuff, and indeed for all other methods in classes, why not for constructors? That just doesn't make sense to me. -- KristofferLawson
The issue is not that JavaInterfacesCannotSpecifyConstructors
but that Java classes
(rather than instances) cannot implement interfaces because they are not really objects. You can write static methods that belong to a class but not declare that the class object itself implements some interface with those static methods.