A design question..
P.java is an abstract class with atleast abstract method
public abstract class P {
public abstract void foo(int x, int y, int z);
}
There are tons of concrete classes that derive from this class and implement foo(int x, int y, intz).
At a later stage the designer of wants to modify the functionality of foo(..) method. To give you a flavor of the change the designer wants to do:
he wants to perform some preprocessing before foo(..) actually gets invoked, then foo(..) call, then some post processing.
the intent in terms of code:
public class P {
public void preprocess() {
..
}
public void foo(int x, int y, int z) {
preprocess();
call derived classe's foo()
postprocess();
}
public void postprocess() {
...
}
}
How could he call derived classes foo in the base class?
Or are there any other solutions that can achieve the effect without having to modify any of the of existing derived classes ?
Your solution should observe two constraints:
- No changes could be made to existing derived classes
- No changes could be made to the client of P. There is a lot of code that instantiates the derived classes of type "P" and invokes foo(int x, int y, int z). You solution should not require any changes there also.
[1402 byte] By [
jdckevi] at [2007-9-26 7:28:19]

I can't see a way to do this. Challenging question and I'll be very interested to hear of a solution that meets your constraints.
Really, an abstract method is like an interface method. It describes a contract that the subclass must fulfill but that's all, the super class doesn't really have any relationship to the subclass beyond the contract it must fulfill. i.e. a subclass calling the abstract method is not really having anything to do its super class (you can't intercept it at the super class).
Sorry, I didn't really have much to add...
First off, in second verion obviously foo() is not abstract.
To reiterate what schillj said:
"a subclass calling the abstract method is not really having anything to do its super class (you can't intercept it at the super class)."
Same way, overriding foo() [non abtract] would also mean that any foo() message that is sent to your subclass will not go to the superclass. In other words, P's foo will never get called.
Now if you don't want to change client's code, you can achieve that by doing:
public void foo(int x, int y, int z) {
preprocess();
this.realFoo(x,y,z);
postprocess();
}
public void realFoo(int x, int y, int z) {} //this can be abstract
//realFoo is what subclasses implemented instead of foo
Only thing is that you would have to change foo() to realFoo() in all derived classes. Of course, clients will still call foo() so no change is needed there.
Also, if your clients use factories instead of directly instantiating derived classes, you can use Dynamic Proxies in java 2(1.3) to create a proxy doing the appropriate processing in invoke(). And Factory would return a proxy instead.
With this approach no code change is needed in either subclasses or clients.
You can use the template pattern (gof) with hook methods.
/**
* Classes implementing P should either override foo()
* or doFoo(). If they dont override foo() (and hence
* override doFoo()), they can also optionally override
* doFooPreprocess() for preprocessing.
*/
public abstract class P
{
public void foo(int x, int y, int z)
{
doFooPreprocess(x, y, z);
doFoo(x, y, z);
}
protected void doFooPreprocess(int x, int y, int z)
{
// no-op impl as implementing classes
// are not required to perform preprocessing
}
protected void doFoo(int x, int y, int z)
{
// this method should be overridden if an
// implementation class wants preprocessing
throw new UnsupportedOperationException(
"Implementing class should either override "
+ "foo() or doFoo(). If they override doFoo() "
+ "they can also override doFooPreprocess()");
}
}
I think this solution fits your needs.
cheesr
dim
dimc at 2007-7-1 17:23:55 >

> You can use the template pattern (gof) with hook
> methods.
>
> /**
> * Classes implementing P should either override foo()
>
> * or doFoo(). If they dont override foo() (and hence
>
> * override doFoo()), they can also optionally
> override
> * doFooPreprocess() for preprocessing.
> */
> public abstract class P
> {
> public void foo(int x, int y, int z)
> {
> doFooPreprocess(x, y, z);
> doFoo(x, y, z);
> }
>
> protected void doFooPreprocess(int x, int y, int
> int z)
> {
> // no-op impl as implementing classes
> // are not required to perform preprocessing
> }
>
> protected void doFoo(int x, int y, int z)
> {
> // this method should be overridden if an
> // implementation class wants preprocessing
> throw new UnsupportedOperationException(
> "Implementing class should either
> hould either override "
> + "foo() or doFoo(). If they override
> override doFoo() "
> + "they can also override
> override doFooPreprocess()");
> }
> }
>
> I think this solution fits your needs.
>
> cheesr
> dim
This is not a solution. The subclasses of P all implement the foo() method, NOT doFoo(). Inside subclasses of P, the foo() methods do not call super.foo() so there is NO way to get back to the P class.
Thinking about this further, the only way to enable such a design would be to have initially made the P class like so:
abstract class P
{
protected void preFunc(int x, int y, int z) { }
abstract protected void funcImpl(int x, int y, int z);
protected void postFunc(int x, int y, int z) { }
final public void func(int x, int y, int z)
{
preFunc(x,y,z);
funcImpl(x,y,z);
postFunc(x,y,z);
}
}
Now, subclasses of P MUST implement funcImpl. This is the implementation of the function. They can also (optionally) implement preFunc() and postFunc() for pre- and post-processing. Users of P-derived objects can only call func(x,y,z). The subclass determines what is done prior, during and after the func() "call".
I'm not sure if this is what is mean by "proxy", but that's what I would name the above concept. For example the following class would do no pre- or post- processing and would simply print a simple text message:
class Sub extends P
{
protected void funcImpl(x, y, z)
{
System.out.println("Inside Sub.func");
}
}
User's of this class would do the following:
Sub s = new Sub();
s.func(1, 2, 3);
I do not pretend this is a solution to your problem since it means you would have to do massive rewrites, but it is a consideration for future design.
> I'm not sure if this is what is mean by "proxy", but> that's what I would name the above concept. Hi schillj, I was referring to Dynamic Proxies introduced recently in Java. http://java.sun.com/j2se/1.3/docs/guide/reflection/proxy.html
>
> public class P {
> public void preprocess() {
> ..
> }
> public void foo(int x, int y, int z) {
> preprocess();
> call derived classe's foo()
> postprocess();
> }
> public void postprocess() {
> ...
> }
> }
>
...
> Your solution should observe two constraints:
> - No changes could be made to existing derived
> classes
> - No changes could be made to the client of P. There
> is a lot of code that instantiates the derived classes
> of type "P" and invokes foo(int x, int y, int z). You
> solution should not require any changes there also.
>
If I understand your problem and contstraints properly, then I don't think it can be done. You have a bunch of code that calls something.foo(), right? And that foo is overridden/implemented by a bunch of derived classes right? And you can't change the call to something.foo(), and you can't change the derived classes' implementation of foo, right?
I don't see any way you can meet those constraints and still get the behavior you want. Ideally, you'd either 1) change all the calls to something.foo() to something.foo2(), which in turn calls pre(), foo(), post(). foo2 would be final, and foo would be abstract.
or
2) change foo() to pre(), derviedFoo(), post(), make foo() final and change all the derived classes' foo() implementations to derivedFoo().
Either approach amounts to the same structure. The only difference is where you make the changes--clients of foo() or implementors of foo().
I'll be watching this thread. I'm interested to see how you resolve this.
jverd at 2007-7-1 17:23:55 >

> This is not a solution. The subclasses of P
> all implement the foo() method, NOT doFoo(). Inside
> subclasses of P, the foo() methods do not call
> super.foo() so there is NO way to get back to the P
> class.
ok, ok... steady on.
My understanding was that the initial author did not want to run around changing lots of other classes that already implement the abstract class. I also assumed (I think incorrectly now that I re-read the initial post) that the requirement was based on the need to change the behaviour of new classes, not existing ones. If all behaviour should be changed, then as you so quietly pointed out, this is not a solution.
In that case, there is no way to do what is being asked without changing some code somewhere. I would suggest changing the code to use the template method, as its exactly what is required. But given the requirements:
a) no change in client code
b) no change in server (implementation) code
there's no way to change what happens when the client calls the server.
cheers
dim
dimc at 2007-7-1 17:23:55 >

I think, as you surmise, that none of the subclasses can be changed, and none of the client code (i.e. the _usage_ of the foo() method) can be changed. However, he/she is asking if the implementation of P could be changed in some way as to not break any existing functionality but to "trap" or "catch" any calls to the abstract foo() method.
> > I'm not sure if this is what is mean by "proxy",
> but
> > that's what I would name the above concept.
>
> Hi schillj, I was referring to Dynamic Proxies
> introduced recently in Java.
> http://java.sun.com/j2se/1.3/docs/guide/reflection/prox
> .html
This is a great link, ashutosh. Thanks.
If he uses Factory classes to generate his subclasses of P, I think this is his best shot. You would have to:
public interface FooIF {
public void foo(int x, int y, int z);
}
and change P to:
public class P implements FooIF { // no longer an abstract class
public void foo(int x, int y, int z) {} // empty implementation
}
Now the subclasses should not have to change.
He needs a Proxy class like:
class PProxy implements InvocationHandler {
private Object Obj;
public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new PProxy(obj));
}
private PProxy(Object obj)
{ Obj = obj; }
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
{
Object result = null;
if( !m.getName().equals("foo"))
return result;
preProcess(args);
try {
result = m.invoke(obj, args);
}
catch(InvocationTargetException e) {
throw e.getTargetException();
}
catch(Exception e) {
e.printStackTrace(System.err);
System.exit(0);
}
finally {
postProcess(args);
}
return result;
}
void preProcess(Object[] args) {}
void postProcess(Object[] args) {}
}
Now, his factory would have to change from:
class PFactory {
public P getPObject() {return new SubclassOfP();}
}
to
class PFactory {
public P getPObject() {
return (P) PProxy.newInstance(new SubClassOfP());
}
}
Dynamic Proxies are very powerful, but I would argue its not the best solution. If he/she is already using a factory for constructing subclasses, then I'd suggest something like the following:
have a delegate implementation of Foo:
public class PDelegate extends P
{
private P delegate;
public PDelegate(P delegate)
{
this.delegate = delegate;
}
public void foo(int x, int y, int z)
{
preprocess(x, y, z);
delegate.foo(x, y, z);
}
}
of course you'll need the preprocess method in P:
public class P
{
// rest of P...
private void preprocess(int x, int y, int z)
{
// preprocessing logic goes here.
}
}
Change the factory by renaming the old getP method to getPImpl and making it private, and create a new getP method:
public class PFactory
{
private P getPImpl( ... )
{
// old implementation of getP
}
public P getP( ... )
{
P old = getPImpl( ... );
return new PDelegate(old);
}
}
That way there's minimal code change, and you've got a centralized preprocessing point in P. This of course all hinges on the presumption that a Factory is being used.
Without harping... DynamicProxies are _very_ powerful, but they have their place. I'd argue it isn't here.
cheers
dim
dimc at 2007-7-1 17:23:55 >

oops, rushed that a bit. The class I call PDelegate should really be called PProxy.cheersdim
dimc at 2007-7-1 17:23:55 >

Each call to p.foo() in a client is resolved polymorpically to the implementation in the particular subclass which p is an instance of. No change to P can have any effect on what happens at execution time. So the goal can't be fully acheived.
But we can limit the changes to require a change only in the code that creates the subclass instances, by making a class public class PWrapper extends P {
private final P myP;
public PWrapper(P p) {myP=p;}
public void foo(int x, int y, int z) {
preprocess();
myP.foo(x,y,z);
postprocess();
}
}
Then each lineP p = new PA();
must be replaced with P p = new PWrapper(new PA());
This avoids the need to change the subclasses at any rate.
I'd argue that if you're going to start changing client code, it'd be a good thing to do to introduce a factory method if its not there already. Its a very easy way to provide flexibility.cheersdim
dimc at 2007-7-1 17:23:56 >

Can you define the distinction between a delegate and a proxy please?
The delegate is the class that the proxy delgates to. So calling the proxy the delegate was misleading. So what it should be is:
public class PProxy extends P
{
private P delegate;
public PProxy(P delegate)
{
this.delegate = delegate;
}
// etc...
}
make sense?
cheesr
dim
dimc at 2007-7-1 17:23:56 >

If the article below is right youare mistaking delegation with forwarding: http://www.javaworld.com/javaworld/javaqa/2001-09/01-qa-0914-delegate.html?Spieler