Defining a constructor in an Interface

C

Chris Berg

An interface forces the implementor to write the code for all the
(abstract) methods. Fine. But can I also enforce a specific
constructor footprint?

Maybe it sounds silly, but it isn't: I am constructing objects using
reflection, for instance:

String newClassName = "mypackage.MyInterface";
// (actually a run-time parameter, not a constant)
Class[] clss = new Class[]{java.util.Properties.class};
Class clazz = Class.forName(newClassName);
Constructor constr = clazz.getConstructor(clss);
MyInterface myObject = (MyInterface)constr.newInstance(objss);

So, I want to make sure that the new class actually has a constructor
with the given parameter(s).

I don't think I can use a static factory method, 'cause that would
require an actual instance of the class, which I don't have, I just
have it's name. Dilemma!

(PLEASE, ALL! Don't start a long thread with pro's and con's about
reflection, that is NOT the point here!)

Chris
 
T

Tjerk Wolterink

Chris said:
An interface forces the implementor to write the code for all the
(abstract) methods. Fine. But can I also enforce a specific
constructor footprint?

You cannot instantie interfaces,
interfaces define the methods that an class wich implement theinterface
should implement.

So if you have a instance of class A whos implementing interface B,
then youre sure that A has the methods of B.

An constructor in an interface is just not possible.
I cant explain it 1 2 3.

But what you can do is something like this:

interface MyInterface {
public MyInterface getInstance(ArgTypeA a, ArgtypeB b, etc);
}

class Implementor implements myInterface {
Implementor(ArgTypeA a, ArgtypeB b, etc) {

}

public MyInterface getInstance(ArgTypeA a, ArgtypeB b, etc) {
return new Implementor(a, b, etc);
}
}

hope you get my point
Maybe it sounds silly, but it isn't: I am constructing objects using
reflection, for instance:

String newClassName = "mypackage.MyInterface";
// (actually a run-time parameter, not a constant)
Class[] clss = new Class[]{java.util.Properties.class};
Class clazz = Class.forName(newClassName);
Constructor constr = clazz.getConstructor(clss);
MyInterface myObject = (MyInterface)constr.newInstance(objss);
 
C

Chris Smith

Chris Berg said:
An interface forces the implementor to write the code for all the
(abstract) methods. Fine. But can I also enforce a specific
constructor footprint?

No, you can't. At some point, you will need to just document
requirements for creating instances. It's a bit messy, but necessary.

That said, I don't think there's ever a good excuse for requiring a
constructor that takes parameters. If you need to pass data to be used
when creating an object of some dynamically determined class, then you
should provide *two* interfaces:

public interface MyInterface { ... }

public interface MyInterfaceFactory
{
public MyInterface create(int a, String b);
}

(You're right that you can't accomplish your goals with a static factory
method, but an abstract factory is used here instead.)

It's very easy for people to remember that their class needs a default
constructor, but it's far more difficult to remember the exact types and
sequence of parameters that you require. Use of reflection's
Constructor class should be limited to truly dynamic utilities that
don't know what API they should expect from the class.

Every time I've broken that rule, I have ended up regretting it later.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
T

Tor Iver Wilhelmsen

Chris Berg said:
An interface forces the implementor to write the code for all the
(abstract) methods. Fine. But can I also enforce a specific
constructor footprint?

No. A constructor's purpose is to initialize fields; an interface does
not care about firlds only method contracts.
So, I want to make sure that the new class actually has a constructor
with the given parameter(s).

No, you want to make sure the object has a no-parameter constructor,
which is the most common way of doing what you want.
 
L

Lee Fesperman

Chris said:
An interface forces the implementor to write the code for all the
(abstract) methods. Fine. But can I also enforce a specific
constructor footprint?

No, you can't. Simply, it is incompatible with the nature of an interface. If you want
more details, google for it in c.l.j.p. It has been discussed a number of times in the
past, and I've provided solid reasons why it must not be done.

As others have suggested, require a no-args constructor and define a class initializer
in the interface, like init(...). It really is a better way.
 
H

Hemal Pandya

Chris said:
An interface forces the implementor to write the code for all the
(abstract) methods. Fine. But can I also enforce a specific
constructor footprint?

Footprint, surely not. But you mean signature. You cannot enforce that
either, as others have already pointed out. But since you are using
reflection, you can look for a constructor that has a specific
signature.
Maybe it sounds silly, but it isn't: I am constructing objects using
reflection, for instance:

String newClassName = "mypackage.MyInterface";
// (actually a run-time parameter, not a constant)
Class[] clss = new Class[]{java.util.Properties.class};
Class clazz = Class.forName(newClassName);
Constructor constr = clazz.getConstructor(clss);

This will obviously fail if mypackage.MyInterface is indeed an
interface, because interfaces do not have constructors.
MyInterface myObject = (MyInterface)constr.newInstance(objss);

So, I want to make sure that the new class actually has a constructor
with the given parameter(s).
But perhaps mypackage.MyInterface is not an interface but implements
some other interface, to which you will you intend to cast the
generated object.

This will work as you expect. If MyInterface has a constructor wiwth
desired signatue it will be returned otherwise NoSuchMethodException
will be throws. Of course, you cannot enforce that the constructor will
use the passed parameter in any sensible manner.

OTOH if MyInterface /is/ an interface, you are going to require the
runtime parameter to be the name of an actual class that implements
that interface, as the following example explains:

import java.lang.reflect.*;
import java.util.Properties;

interface Inter {
public static class Impl
{
public static void main(String args[]) throws Exception {
Properties p = new Properties(); p.setProperty("this", "works");
createInter("GoodInter", p);
createInter("BadInter", p);
}
static Inter createInter(String className, Properties params) throws
Exception {
Class[] clss = new Class[]{Properties.class};
Class clazz = Class.forName(className);
Constructor constr = clazz.getConstructor(clss);
Inter myObject = (Inter)constr.newInstance(new Object[]{params});
return myObject;
}
}
}

class GoodInter implements Inter {
public GoodInter(Properties p){
System.out.println("In GoodInter:<init>(Properties)");
p.list(System.out);
}
}


class BadInter implements Inter {
public BadInter(){
System.out.println("In BadInter:<init>()");
}
}
I don't think I can use a static factory method, 'cause that would
require an actual instance of the class, which I don't have, I just
have it's name. Dilemma!

(PLEASE, ALL! Don't start a long thread with pro's and con's about
reflection, that is NOT the point here!)
hth.


Chris

-hemal
 
T

Thomas Weidenfeller

Chris said:
That said, I don't think there's ever a good excuse for requiring a
constructor that takes parameters.

Well, such a requirement, or lets better say nice-to-have feature, can
come up when you want to have a 1:1 translation of your design model to
an implementation. I perfectly understand (at least I think so) why
things are as they are, but it would be nice to have it otherwise.

Assume you have modeled some resource reservation system with a
ResourceRequest class and a User class. A ResourceRequest is always
associated with a User requesting a resource in your model. There should
never be a ResourceRequest without one.

To ensure this it would be easy to have a constructor

public ResourceRequest(User user) { }

You would just have to guard for a null argument in the constructor. If
you write a Bean or have other reasons to only have a no-argument public
constructor you make it easier to misuse the ResourceRequest class,
because people can suddenly construct ResourceRequests without an
associated User.

So you have a case where it is required to follow some additional
convention in order to use a class correctly. One more source for
potential bugs. You can of course work around this by providing a
factory for constructing ResourceRequests which enforces the
requirement. But you have to write more code. More code - more potential
bugs.

/Thomas
 
L

Lee Fesperman

Thomas said:
Well, such a requirement, or lets better say nice-to-have feature, can
come up when you want to have a 1:1 translation of your design model to
an implementation. I perfectly understand (at least I think so) why
things are as they are, but it would be nice to have it otherwise.

Nope, it's still a bad idea. A decent implementation is likely to want additional
arguments to its constructor. It pretty much kills multiple inheritance of interfaces
because of conflicting constructor requirements. If your implementation wishes to extend
another class with specific constructor requirements, you have no recourse.

There is more. Google for previous discussions on this.
 
B

Bent C Dalager

As others have suggested, require a no-args constructor and define a
class initializer
in the interface, like init(...). It really is a better way.

I have based my (non-factory-based) immutables on getting all their
state through the ctor, but the question posed indicates that this
isn't always feasible.

Is an init() method considered a viable way to make immutable objects?
While you could write init() in such a way that any calls beyond the
first are ignored, it seems a bit kludgy. If nothing else, clients
could end up using instances that haven't had init() called on them
yet and then their contents _can_ theoretically change at some later
point.

Cheers
Bent D
 
T

Thomas Weidenfeller

Lee said:
Nope, it's still a bad idea. A decent implementation is likely to want additional
arguments to its constructor. It pretty much kills multiple inheritance of interfaces
because of conflicting constructor requirements. If your implementation wishes to extend
another class with specific constructor requirements, you have no recourse.

There is more. Google for previous discussions on this.

I am not saying it is a good idea. I am just saying that I don't agree
with Chris' claim:

/Thomas
 
C

Chris Berg

I'm overwelmed by the responses, thanks, all.

For one thing, I made an error i the originals post:

String newClassName = "mypackage.MyInterface";

should read

String newClassName = "mypackage.MyClass";
// (class that implements MyInterface)

This has made some confusion, sorry about that.

On the other hand, solving this particular problem would not make me
happy, I can see that now. As the class name comes from the
user/implementor at run-time, is could be erroneous in a number of
ways:

- specify a non-existing class file
- specify a file that is not a valid .class file
- specify a class that does not implement the interface
- specify a class that does implement the interface, but that lacks
one or more of its methods (possible if he made his own version of the
interface - unlikely, but possible).

If I choose the default-constructer-plus-init-method solution, I'm
still not home free.

The real reason why I want to specify a specific constructor is that
the Exception thrown during construction is difficult to descipher by
the user, resulting in me getting lots of "What does this error mean"
e-mails.

So I guess the solution lies elsewhere, I see that now: I must make a
better exception handler, telling the user more about what has
happened.

BUT! It would be nice to have a sort of 'run-time class file verifyer'
that could verify a class file BEFORE you try to instantiate it. That
would really make my day!

Chris
 
R

Raymond DeCampo

Lee said:
Nope, it's still a bad idea. A decent implementation is likely to want additional
arguments to its constructor. It pretty much kills multiple inheritance of interfaces
because of conflicting constructor requirements. If your implementation wishes to extend
another class with specific constructor requirements, you have no recourse.

Just because there are drawbacks, doesn't make it a bad idea. First of
all, if such a thing were added to the language, interfaces wouldn't
necessarily be required to specify a constructor signature. So
everything that exists currently would still work exactly as it does.
Second, if one were to use said functionality, one would have to be
aware of the implications (as indicated in your post).

That said, I think we can live without this particular feature in the
Java language.

Ray
 
J

John Currier

That said, I don't think there's ever a good excuse for requiring a
constructor that takes parameters.

Exactly how would you implement an immutable class? Take something
like String as an example. Would it be full of setters that tried to
emulate the behavior of a constructor but threw exceptions if another
setter had already been called?

John
http://schemaspy.sourceforge.net
 
C

Chris Smith

John Currier said:
Exactly how would you implement an immutable class? Take something
like String as an example. Would it be full of setters that tried to
emulate the behavior of a constructor but threw exceptions if another
setter had already been called?

Nope, of course not.

To put this back into the original context, which was lost by selective
quoting, my above comment refers to classes which are intended to be
instantiated by reflection and used via a known interface. The
reference to java.lang.String is confusing and irrelevant. A class
instantiated by reflection is not going to be a value object in the
sense that String is.

However, such a class could certainly need to be given state for
initialization, and even immutable state. As I (very clearly) clearly
said in my original post, you would provide an abstract factory class,
which has a constructor with no arguments, and use that class's methods
to build the other object that requires initialization.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

John Currier

Okay, but you made an unqualified absolute statement. I erroneously
interpreted your post to mean that you didn't think that there was ever
a good excuse for requiring a constructor that takes parameters. My
mistake.

John
 
J

John C. Bollinger

Bent said:
I have based my (non-factory-based) immutables on getting all their
state through the ctor, but the question posed indicates that this
isn't always feasible.

Is an init() method considered a viable way to make immutable objects?
While you could write init() in such a way that any calls beyond the
first are ignored, it seems a bit kludgy. If nothing else, clients
could end up using instances that haven't had init() called on them
yet and then their contents _can_ theoretically change at some later
point.

You have raised the points that I would have done. I don't like the
approach. Wrapping the object creation in a factory allows you to avoid
these issues, by allowing you to keep the init() method (or other
initialization mechanism, such as a constructor) hidden from the
object's users, and by not allowing anyone to ever see an uninitialized
instance.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top