Defining a constructor in an Interface

Discussion in 'Java' started by Chris Berg, Jun 29, 2005.

  1. Chris Berg

    Chris Berg Guest

    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
     
    Chris Berg, Jun 29, 2005
    #1
    1. Advertising

  2. Chris Berg wrote:
    > 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);
    >
     
    Tjerk Wolterink, Jun 29, 2005
    #2
    1. Advertising

  3. Chris Berg

    Chris Smith Guest

    Chris Berg <> wrote:
    > 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
     
    Chris Smith, Jun 29, 2005
    #3
  4. Chris Berg <> writes:

    > 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.
     
    Tor Iver Wilhelmsen, Jun 29, 2005
    #4
  5. Chris Berg wrote:
    >
    > 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.

    --
    Lee Fesperman, FFE Software, Inc. (http://www.firstsql.com)
    ==============================================================
    * The Ultimate DBMS is here!
    * FirstSQL/J Object/Relational DBMS (http://www.firstsql.com)
     
    Lee Fesperman, Jun 30, 2005
    #5
  6. Chris Berg

    Hemal Pandya Guest

    Chris Berg wrote:
    > 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
     
    Hemal Pandya, Jun 30, 2005
    #6
  7. Chris Smith wrote:
    > 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


    --
    The comp.lang.java.gui FAQ:
    ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq
    http://www.uni-giessen.de/faq/archiv/computer-lang.java.gui.faq/
     
    Thomas Weidenfeller, Jun 30, 2005
    #7
  8. Thomas Weidenfeller wrote:
    >
    > Chris Smith wrote:
    > > 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.


    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.

    --
    Lee Fesperman, FFE Software, Inc. (http://www.firstsql.com)
    ==============================================================
    * The Ultimate DBMS is here!
    * FirstSQL/J Object/Relational DBMS (http://www.firstsql.com)
     
    Lee Fesperman, Jun 30, 2005
    #8
  9. In article <>,
    Lee Fesperman <> wrote:
    >
    >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
    --
    Bent Dalager - - http://www.pvv.org/~bcd
    powered by emacs
     
    Bent C Dalager, Jun 30, 2005
    #9
  10. Lee Fesperman wrote:
    > 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:

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


    /Thomas

    --
    The comp.lang.java.gui FAQ:
    ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq
    http://www.uni-giessen.de/faq/archiv/computer-lang.java.gui.faq/
     
    Thomas Weidenfeller, Jun 30, 2005
    #10
  11. Chris Berg

    Chris Berg Guest

    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
     
    Chris Berg, Jun 30, 2005
    #11
  12. Lee Fesperman wrote:
    > Thomas Weidenfeller wrote:
    >
    >>Chris Smith wrote:
    >>
    >>>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.

    >
    >
    > 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

    --
    XML is the programmer's duct tape.
     
    Raymond DeCampo, Jun 30, 2005
    #12
  13. Chris Berg

    John Currier Guest

    > 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
     
    John Currier, Jul 1, 2005
    #13
  14. Chris Berg

    Chris Smith Guest

    John Currier <> wrote:
    > > 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?


    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
     
    Chris Smith, Jul 1, 2005
    #14
  15. Chris Berg

    John Currier Guest

    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
     
    John Currier, Jul 1, 2005
    #15
  16. Bent C Dalager wrote:
    > In article <>,
    > Lee Fesperman <> wrote:
    >
    >>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.


    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.

    --
    John Bollinger
     
    John C. Bollinger, Jul 2, 2005
    #16
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Raffael Vogler
    Replies:
    8
    Views:
    1,162
    Chris Uppal
    Nov 30, 2003
  2. Replies:
    0
    Views:
    345
  3. johny smith
    Replies:
    8
    Views:
    420
    Peter Koch Larsen
    Jul 2, 2004
  4. Wayne Shu
    Replies:
    6
    Views:
    348
    Wayne Shu
    Jan 28, 2007
  5. Generic Usenet Account
    Replies:
    10
    Views:
    2,244
Loading...

Share This Page