Constructor

M

Martin Gregorie

I have *definitely* seen such errors when trying tricks very much like
this (tricks that I now realize were ill-advised), involving trying to
export "this" in some manner from a constructor.

Perhaps some implementations have additional "rules" to try to protect
users from doing exactly this sort of thing?

Did you actually compile it?

I just did (Sun JDK 1.6.0_07). It compiled and ran once a couple of line
wraps introduced by Pan were fixed.
 
Z

zerg

Tom said:
This more or less what i was thinking - convert inheritance to
composition, and do the registration in the wrapper after the
implementation is constructed.

This also resembles decorator, but the changeable part is the core
instead of the wrapper.

Of course, calling subclass specific methods might be a pain, unless you
use generics to make the wrapper a kind of "one-element container" with
a get method that returns the object.

The wrapper would be better named something like "RegisteredFoo" to
indicate that it wraps a Foo and registers it -- wherever the Foo that
is passed in must be registered something like RegisteredFoo<?> would be
the parameter type instead of just Foo.
 
T

Tom Anderson

This also resembles decorator, but the changeable part is the core instead of
the wrapper.

Of course, calling subclass specific methods might be a pain,

Yes - if the subclasses extend the interface rather than just the
implementation, this approach doesn't work at all.
unless you use generics to make the wrapper a kind of "one-element
container" with a get method that returns the object.

The wrapper would be better named something like "RegisteredFoo" to
indicate that it wraps a Foo and registers it -- wherever the Foo that
is passed in must be registered something like RegisteredFoo<?> would be
the parameter type instead of just Foo.

Not a bad idea. If you do this, it really does start to look a lot like
Decorator, you're right.

My second approach, of not using a wrapper but doing the registration
post-construction in a factory method, lets the subclasses extend the
interface, but since the factory method returns the base type, you do have
to do an explicit cast first.

Although you could do something like this:

public <T extends Implementation> T create(Class<T> implClass) {
T impl = implClass.newInstance() ;
register(impl) ;
return impl ;
}

You could use a more complicated reflective invocation instead of
newInstance, or you could do something clever with factories:

public <T extends Implementation> T create(ImplFactory<T> implFactory) {
T impl = implFactory.create(some args) ;
register(impl) ;
return impl ;
}

The trouble with this is you then have to write factories for each
implementation subclass, and it starts to look like you've got at least
one too many layers of indirection here!

tom
 
Z

zerg

Tom said:
public <T extends Implementation> T create(ImplFactory<T> implFactory) {
T impl = implFactory.create(some args) ;
register(impl) ;
return impl ;
}

The trouble with this is you then have to write factories for each
implementation subclass, and it starts to look like you've got at least
one too many layers of indirection here!

That's all right. Whenever I see a problem like that, I tend to solve it
quite simply, usually by adding one more layer of indirection ...

:)
 
S

Simon

There are ways to reach a reference without it being assigned,

Usually I would say: "I don't agree", but since both you and Patricia
independently posted almost the same piece of code I'd better be more
careful :)
Foo foo; // I hate including 'Class' or 'object' in identifiers
try
{
foo = new Foo();
}
catch ( Exception exc )
{
// completely fail to handle exc
}
foo.doStuff(); // error

This piece of code is not *bad* enough: It doesn't compile :)
Unless you assign some value to foo in every execution path, in
particular also inside the catch block, it will result in a compilation
error:
"variable object might not have been initialized"

Clearly, you can assign null to foo inside the catch block, making the
code even worse, but can you really reach an unassigned reference?

The document you were citing says:

"Each local variable [...] must have a definitely assigned value when
any access of its value occurs."
(where "access" means occuring anywhere in an expression except on the
lhs of a "=").

Nit-picking,
Simon
 
P

Patricia Shanahan

Simon wrote:
....
"Each local variable [...] must have a definitely assigned value when
any access of its value occurs."
(where "access" means occuring anywhere in an expression except on the
lhs of a "=").

My example dealt with this by initializing foo:

<*bad* code>
MyClass object = null;
try {
object = new MyClass(someArgument);
} catch (Exception e){
System.err.println("MyClass constructor failure "+e.getMessage());
}
object.doStuff();
</*bad* code>

I don't think it is a good idea to initialize a local variable with a
value that is not intended to be used. It is potentially disastrous when
combined with a badly written try-catch. However, it does seem to happen.

Patricia
 
S

Simon

My example dealt with this by initializing foo:

Right, I missed that when comparing it to Lew's code, though this was
probably the most obvious place to look at :)
 

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