A Java "interface" declaration does not allow a constructor to be specified in it ...

  • Thread starter Casey Hawthorne
  • Start date
C

Casey Hawthorne

A Java "interface" declaration does not allow a constructor to be
specified in it -- has this been fixed in Java 1.5?
 
A

Andrew Thompson

A Java "interface" declaration does not allow a constructor to be
specified in it -- has this been fixed in Java 1.5?

It was never broken, and I very much doubt it will ever be changed.

On what faulty reasoning do you feel you require an interface
with a constructor? (Note that I may not be qualified to supply
the solution, but am confident others can)
 
T

Tony Morris

Casey Hawthorne said:
A Java "interface" declaration does not allow a constructor to be
specified in it -- has this been fixed in Java 1.5?

It was never broken. There is good reason for this.
Without writing a 2000 page essay, I can perhaps recommend a solution that
seems to fit the *real* problem when this flawed train of thought arises
since I see it every so often.
I'm speculating you want to enforce that implementations are constructed
such that they take 1 or more arguments.
This is not a correct idea to have - after all, how will you access that
member? Constructors and interfaces should be thought of independantly,
since a constructor belongs only in an implementation (it's only logical
after some thought).
What you possibly want is the ability to access some member of an
implementation - this is easily achieved by providing an accessor method on
the interface.

Without more information, only speculation can be provided.
The only 'concrete' thing that can be said is that you have not provided a
problem, but a broken solution.
I have seen this more times over the years than I care to remember (perhaps
in the hundreds?) - I decided to call it YARD - Yet Another Requirements
Defect.
 
T

Tor Iver Wilhelmsen

Casey Hawthorne said:
A Java "interface" declaration does not allow a constructor to be
specified in it -- has this been fixed in Java 1.5?

What is to fix? An interface is defined to represent a method
"contract" for a class. Constructors do not count as methods for that
purpose. You cannot, and were never meant to, "construct" interfaces,
just objects of classes implementing the interface.
 
M

Mark Thornton

Casey said:
A Java "interface" declaration does not allow a constructor to be
specified in it -- has this been fixed in Java 1.5?

You have always been able to specify an interface for factory classes,
which is what you ought to use for this purpose.
It might be nice syntactic sugar if one could add methods to 'Class'
that could then serve as the factory (similar to SmallTalk), but that
wouldn't come very high on my priority list for changes.

Mark Thornton
 
C

Chris Uppal

Casey said:
A Java "interface" declaration does not allow a constructor to be
specified in it -- has this been fixed in Java 1.5?

An interface defines one aspect of the API to an /object/, part of that
object's behaviour. Creating itself is not part of the object's behaviour so
it doesn't belong in the interface.

Now what you might want to do is find /another/ object who's job it is to
create instances of the first class (or interface). /That/ object's role can
be specified by an interface with no problem. Such
objects-that-create-other-objects are normally called "factories". Factories
don't have to be interfaces (most often they aren't), but they can be specified
by them. E.g:

E.g.

==========

public interface Actor
{
void performSomeAct();
void performSomeOtherAct();
}

public interface ActorFactory
{
Actor makeActor();
}

==========


And then you might have concrete implementations. Here's a slightly
complicated example with three kinds of factory object that share the same
factory interface (the complexity is necessary to illustrate /why/ you might
want to use factory interfaces in the first place). Note that nearly
everything is package-private:

==========

//////// The public bit ////////

public class OverallSystem
{
public ActorFactory getDummyFactory() { return new DummyFactory() };
public ActorFactory getDeploymentFactory() { return new RealFactory() };
public ActorFactory getDebugFactory() { return new
DebugFactory(getDummyFactory()) };
}

//////// Some private factory classes ////////

class DummyFactory implements ActorFactory
{
Actor makeActor() { return new DummyActor(); }
}

class RealFactory implements ActorFactory
{
Actor makeActor() { return new ComplicatedRealActor(); }
}

class DebugFactory implements ActorFactory
{
private final ActorFactory m_subFactory;
DebugFactory(ActorFactory factory) { m_subFactory = factory; }
Actor makeActor() { return new LoggingWrapper(m_subFactory.makeActor()); }
}


//////// Some private Actor classes ////////

DummyActor implements Actor
{
void performSomeAct() { /* ignore it */ }
void performSomeOtherAct() { /* ignore it */ }
}

ComplicatedRealActor implements Actor
{
void performSomeAct() { /* ...complicated code... */ }
void performSomeOtherAct() { /* ...complicated code... */ }
}

LoggingWrapper implements Actor
{
private final Actor m_actor;
LoggingWrapper(Actor actor) { m_actor = actor; }
void performSomeAct() { log("someAct"); m_actor.performSomeAct(); }
void performSomeOtherAct() { log("someOtherAct");
m_actor.performSomeOtherAct(); }
}

==========

-- chris
 
L

Lee Fesperman

Casey said:
A Java "interface" declaration does not allow a constructor to be
specified in it -- has this been fixed in Java 1.5?

This suggested extension to Java has been discussed in the group before. At that time, I
objected to it because of the complications it incurred. My example was a class that
implemented such an interface and also extended another class. The constructor required
for the interface could make it impossible to call the constructor for the super class
because the interface constructor did not provide information required for the super
class constructor.

Your article prompted me to come up with another objection -- If two interfaces had
conflicting constructors, a sub class could not inherit both. This would be a more
onerous restriction than the current restriction on the two interfaces having methods
with the same signature and conflicting return types.

This brings me to wonder how you would handle a sub interface. Would it inherit the
constructor? Could it override a super constructor?

I think the real problem is that you're violating the spirit of interfaces. By
definition, they don't specify implementation. A constructor would tend to imply a
specific implementation.
 
X

xarax

Lee Fesperman said:
This suggested extension to Java has been discussed in the group before. At that time, I
objected to it because of the complications it incurred. My example was a class that
implemented such an interface and also extended another class. The constructor required
for the interface could make it impossible to call the constructor for the super class
because the interface constructor did not provide information required for the super
class constructor.

Your article prompted me to come up with another objection -- If two interfaces had
conflicting constructors, a sub class could not inherit both. This would be a more
onerous restriction than the current restriction on the two interfaces having methods
with the same signature and conflicting return types.

This brings me to wonder how you would handle a sub interface. Would it inherit the
constructor? Could it override a super constructor?

I think the real problem is that you're violating the spirit of interfaces. By
definition, they don't specify implementation. A constructor would tend to imply a
specific implementation.

If Java supported full multiple inheritance (which is
the implication of interface constructors), then there
would be no need for interfaces; just use abstract classes
in place of interfaces.

Full multiple inheritance would require an extension
of the constructor syntax.


public class Fubar
extends Gorko, Snafu, Gecko
{
public Fubar()
{
super /* Start a "super" block */
{
/* Specify the order of the constructors
and the appropriate parameters. */
Gorko();
Snafu();
Gecko();
}
}
}


In the above example, a super block specifies
the order in which the constructors of the parent
classes are called. The default order is the order
in which the parents are specified in the extends
clause, with no parameters. Within the super block,
only constructors can be called and they are identified
by the class name.

With the above extension to the Java language,
there is no need for interfaces, as any number
of abstract classes could be extended and their
respective constructors could be called with
whatever appropriate parameters.

Two cents worth. Your mileage may vary.

--
----------------------------
Jeffrey D. Smith
Farsight Systems Corporation
24 BURLINGTON DRIVE
LONGMONT, CO 80501-6906
http://www.farsight-systems.com
z/Debug debugs your Systems/C programs running on IBM z/OS for FREE!
 
O

Oscar kind

xarax said:
If Java supported full multiple inheritance (which is
the implication of interface constructors), then there
would be no need for interfaces; just use abstract classes
in place of interfaces.

Which poses other problems. Imagine the following (but please bear with
the slightly off analogy):

abstract class Person has a non-abstract method "transport", that
implements walking.

abstract class MailDelivery has a non-abstract method "transport", which
implements mail delivery.

class MailMan extends both, and thus inherits the method transport from both
classes. For some reason, there is no reason to override it. Now please
think about these questions:
- Which one is inherited?
- If one is chosen automatically, what about dependencies in another
superclass? The two methods may have an incompatible contract.
- If the method autometically becomes abstract, why? Abstract methods are
always marked thus (either by the keyword abstract or by being defined
in an interface).
- How do you select the transport method from Person? Extend the syntax
again, with Person.super.transport()? It's hardly efficient to get a
complicated, arcane syntax.
 
X

xarax

Oscar kind said:
Which poses other problems. Imagine the following (but please bear with
the slightly off analogy):

abstract class Person has a non-abstract method "transport", that
implements walking.

abstract class MailDelivery has a non-abstract method "transport", which
implements mail delivery.

class MailMan extends both, and thus inherits the method transport from both
classes. For some reason, there is no reason to override it. Now please
think about these questions:
- Which one is inherited?
Both.

- If one is chosen automatically, what about dependencies in another
superclass? The two methods may have an incompatible contract. n/a

- If the method autometically becomes abstract, why? Abstract methods are
always marked thus (either by the keyword abstract or by being defined
in an interface).

Not abstract.
- How do you select the transport method from Person? Extend the syntax
again, with Person.super.transport()? It's hardly efficient to get a
complicated, arcane syntax.

The child class is the one causing the name conflict.
Therefore there would be a facility to rename one of
the conflicting methods in one of the parent classes.

The Eiffel language has full multiple inheritance. When
a name conflict arises, it is the responsibility of the
inheriting class to resolve the conflict by renaming.
Otherwise, a compile-time error occurs. The renaming is
at the compile-time so that the compiler can distinguish
which parent method is getting called.

Extending the Java language to support full MI requires
such language extensions to specify which constructors
are called (with whatever appropriate parameters), the
order in which those constructors are called, and to
resolve the issue of name conflicts.

On the extends clause where the parents are specified
is likely where the renaming would occur through something
like:

=========================================
public class MailMan
extends Person [rename transport:transportBlah],
MailDelivery
{
public MailMan()
{
super
{
Person();
MailDelivery();
}
}
}
=========================================

I used square brackets '[]', rather than braces '{}',
for the renaming to avoid parsing confusion with the
class body braces. The keyword "rename" is probably
not a good choice, as it is likely already in wide
use as a normal identifier.

Another issue arises with polymorphism when the
MailMan instance is up-cast to either Person or
MailDelivery, and subsequently the "transport"
method is called. If there was no redefinition,
then the non-renamed method would likely be called.

However, redefining a method in the subtype would
require specifying some kind of "preference" as to
which parent method is called.

IIRC, Eiffel uses the term "polymorphic catcalls"
for this situation and there are complicated rules
as to resolving the ambiguity.

In the current Java language, the last redefinition of
a method is the one that takes effect. Implementing
multiple interfaces with the same method signature can
lead to confusion. So, such situations are avoided when
practical (cannot rename inherited methods in Java).

There would also be issues involving the JVM and
the reflection libraries, which presume that an instance
has a linear chain of parents, and interfaces are treated
quite differently from classes.
 
S

Stefan Schulz

=========================================
public class MailMan
extends Person [rename transport:transportBlah],
MailDelivery
{
public MailMan()
{
super
{
Person();
MailDelivery();
}
}
}
=========================================

I don't see any renames for clone(), hashCode(),
toString()... This would be a major hassle. The common
ancestor for all types is a nice thing, but it introduces
a guaranteed set of clashes.

More trouble then it is worth, IMHO.
 
O

Oscar kind

xarax said:

This won't work, because you cannot rename a method and still fullfill the
contract of the superclass:

MailMan extends (is a) Person, so its transport() method must transport
the MailMan.

MailMan extends (is a) MailDelivery, so it's transport() method must
transport the mail items (for example from it's bag to the letterbox).

Is you rename the transport inherited from one of the superclasses, you no
longer fullfil that contract.

This fails, because you can say:

Person mailMan1 = new MailMan();
MailDelivery mailMan2 = new MailMan();

The contract for mailMan1.transport() differs from mailMan2.transport():
one is a Person, and the other is a MailDelivery (even though they are
implemented using a common subclass).


And automatic un-renaming won't work either, because then the same method
has a different name based on the context. That's begging for a
maintenance hell.
 
Joined
Jan 19, 2010
Messages
1
Reaction score
0
Java interfaces not being able to have constructors is a serious design error.

The argument that interfaces shouldn't have constructors because an interface shouldn't be initialized, is faulty. One wouldn't give an interface a constructor to initialize it, but in order to have a contract saying what you can expect implementing classes or sub-interfaces to have. Why should having a constructor not be part of that contract?

My personal use case is: I want to parametrize a breadth first search algorithm with a queue implementation. Optimally, I would like to write code like this:

class BreadthFirstSearch<Q extends Queue<TreeNode>>
{
[...]
nodeQueue = new Q();
[...]
}

This doesn't compile. Since I cannot require Queue implementations to have a contructor, as far as I can see, my only choice is to pass the queue into the BreadthFirstSearch class through its constructor, or something similar. This seems to break encapsulation.
 

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,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top