From: Eric Sosman on
Andreas Leitgeb wrote:
> [...]
> I still see some merit in being able to enforce that any concrete
> class implementing some thusly declared interface had to offer some
> particular c'tor, as a means to help developers of such classes to
> not forget about it.

That doesn't strike me as a great idea, because it constrains
the subclass' implementation rather than its interface. It may be
tempting to view a class' constructors as "sort of methods" and as
such part of the interface, but I don't think it holds up.

Here's my objection: Suppose there's an Entertainer interface
(or abstract class) and I'm writing concrete implementations of it.
I write Actor and Singer, but when I come to Comedian I realize
that every Comedian must have a Joke he can fall back on when the
act is dying: A Comedian without a shop-worn stale Joke is no
Comedian at all. So to ensure that all Comedians are viable, I
give the class a Joke member and initialize it in the constructor:

class Comedian implements Entertainer {
private final Joke jokeOfLastResort;
Comedian(Joke joke) {
if (joke == null)
throw new IllegalArgumentException("not funny");
jokeOfLastResort = joke;
}
...
}

But suppose that Entertainer (somehow) requires all implementing
classes to provide a no-arguments constructor -- maybe even a public
no-arguments constructor. How will a Comedian instantiated with that
constructor acquire his jokeOfLastResort? We can't let it be null (a
Comedian with no Joke would be a Politician), so we're forced to invent
some kind of default Joke the no-arguments constructor can use:

class Comedian implements Entertainer {
... as above ...
private static final Joke DEFAULT =
new Joke("Plato and a platypus walk into a bar...");
public Comedian() {
this(DEFAULT);
}
...
}

Okay, it might make sense for the class of Comedians to have a
default stale Joke (a faithful model of reality, perhaps), but note
that the need for something like DEFAULT was *forced* upon us by the
requirement for a no-arguments constructor. The author of Entertainer,
who knew nothing about the wants and needs of those who would come
later, decreed that every implementing class would have usable default
values for everything that might ordinarily be passed as arguments to a
constructor. Is that much coercive power a good thing to put in the
hands of the Entertainer author?

I guess one could always evade the requirement:

class Comedian implements Entertainer {
...
public Comedian() {
throw new UnsupportedOperationException(
"Please don't use this constructor");
}
...
}

.... but one would then have to wonder about the utility of Expression's
requirement that the constructor exist.

--
Eric.Sosman(a)sun.com
From: Arved Sandstrom on
Marcin Rzeźnicki wrote:
> On 19 Paź, 16:13, Andreas Leitgeb <a...(a)gamma.logic.tuwien.ac.at>
> wrote:
>
>> I still see some merit in being able to enforce that any concrete
>> class implementing some thusly declared interface had to offer some
>> particular c'tor, as a means to help developers of such classes to
>> not forget about it.
>
> Yep, this is not bad.

I prefer the annotations-based method such as described here:
http://www.javaspecialists.eu/archive/Issue167.html

It works very cleanly - my annotations processors are in a separate JAR
that I include on the javac classpath. Strictly speaking there's no need
to specify the processor path if doing this; it will default to the user
classpath if no processor path is specified. The only change I need to
make to my "real" source is the actual annotations, like
@NoArgsConstructor in the example, and quite frankly on the
implementation classes is where I personally want to enforce a condition
like this.

Because of the @Inherited annotation on the @NoArgsConstructor
annotation it becomes particularly handy. I have found use of this
approach when a large number of JPA @Entity classes inherit from a
@MappedSuperclass - it's not uncommon to want to supply some entities
with useful ctors (and if doing so carelessly the no-args ctor goes
away); using this kind of annotation on the @MappedSuperclass catches
all these problems at compile time.

AHS
From: Marcin Rzeźnicki on
On 19 Paź, 17:32, Arved Sandstrom <dces...(a)hotmail.com> wrote:
> Marcin Rzeźnicki wrote:
> > On 19 Paź, 16:13, Andreas Leitgeb <a...(a)gamma.logic.tuwien.ac.at>
> > wrote:
>
> >> I still see some merit in being able to enforce that any concrete
> >> class implementing some thusly declared interface had to offer some
> >> particular c'tor, as a means to help developers of such classes to
> >> not forget about it.
>
> > Yep, this is not bad.
>
> I prefer the annotations-based method such as described here:http://www.javaspecialists.eu/archive/Issue167.html

Nice, it wins :-)

From: Andreas Leitgeb on
Eric Sosman <Eric.Sosman(a)sun.com> wrote:
> Andreas Leitgeb wrote:
>> I still see some merit in being able to enforce that any concrete
>> class implementing some thusly declared interface had to offer some
>> particular c'tor, as a means to help developers of such classes to
>> not forget about it.

> Here's my objection: Suppose there's an Entertainer interface
> (or abstract class) and ...
> ...
> Okay, it might make sense for the class of Comedians to have a
> default stale Joke (a faithful model of reality, perhaps), ...
:-)
> ...
> The author of Entertainer, who knew nothing about the wants and needs
> of those who would come later, ...

Thanks for the entertaining example, but I think it's beside the point.
This type of argument "it's bad for this exemplary usecase, so it must
be bad for all usecases" is obviously flawed. (or was a joke, itself)

On second thought: If the Entertainers were designed to be dynamically
loaded by name, then Comedians just wouldn't have any chance of a individual
default joke. They could offer their Joke- constructor, but unless they
also offered a no-args one, they just wouldn't ever be successfully engaged.

This whole topic is inspired by dynamic loading of classes. Otherwise, there
wouldn't really be any use for dictating constructors at all. Dynamic loading
of classes seems to me of increasing importance with all those AppServers,
J2EE, ... Demanding the default-constructor (or even with a specific set
of arguments) for those classes imposes no new restriction, just formalizes
the restrictions that were already imposed by documentation and use.

PS: In recent threads I spoke up against restrictions, and now I promote them?
It's different types of restrictions, of course: an extra method or c'tor
is easily added as a dummy, but an idly added "final" is much harder to come
by, if deemed improper, later.

From: Andreas Leitgeb on
Marcin Rzeźnicki <marcin.rzeznicki(a)gmail.com> wrote:
> On 19 Paź, 17:32, Arved Sandstrom <dces...(a)hotmail.com> wrote:
>> Marcin Rzeźnicki wrote:
>> > On 19 Paź, 16:13, Andreas Leitgeb <a...(a)gamma.logic.tuwien.ac.at>
>> > wrote:
>> >> I still see some merit in being able to enforce that any concrete
>> >> class implementing some thusly declared interface had to offer some
>> >> particular c'tor, as a means to help developers of such classes to
>> >> not forget about it.
>> > Yep, this is not bad.
>> I prefer the annotations-based method such as described here:
>> http://www.javaspecialists.eu/archive/Issue167.html
> Nice, it wins :-)

Indeed nice, but what would be the extra effort to create e.g. a
@StringArgConstructor annotation and its processing? And then also
a @StringStringArgConstructor and a @StringMyFooIntArgConstructor, ...

As long as this annotation, its processor, and a mechanism to create
annotations for any particular constructor-signature aren't yet in the
standard, I wouldn't deem them a full substitute...

But then again, they do not depend on my deeming it anything... :-)