views:

93

answers:

6

I would like to override a method in an object that's handed to me by a factory that I have little control over. My specific problem is that I want to override the getInputStream and getOutputStream of a Socket object to perform wire logging; however the generic problem is as follows:

public class Foo {
    public Bar doBar() {
        // Some activity
    }
}

Where I'd like to take an instantiated Foo and replace the doBar with my own that would work as follows:

Bar doBar() {
    // My own activity
    return original.doBar();
}

For the Socket I'm going to return an InputStream and OutputStream that are wrapped by logging to intercept the data.

+4  A: 

You can't replace methods in existing objects - you can't change an existing object's type, for one thing.

You could create a new instance of another class which delegated to the existing instance, but that has limitations too.

In your real world case is there no way you can simply make a separate call to wrap the streams returned by the socket? Can you give more details.

Jon Skeet
+6  A: 

Since Java uses class-based OO, this is impossible. What you can do is use the decorator pattern, i.e. write a wrapper for the object that returns the wrapped streams.

Michael Borgwardt
Decorating a Socket is a real pain, but it seems to be my only option. Thanks.
Tyler Szabo
A: 

I'm not sure if this is possible. Have you considered creating your own class, having the object returned by the factory as a member, and then writing the doBar() method for that class.

sjobe
A: 

You can't really change an object on the fly in java.

You could have something which do what you want by wrapping your Foo into another similar objet which will delegate every call to Foo and at the same log everything you want. (see Proxy)

But if you want to do logging, maybe aspect is a better choice. (see AspectJ)

Colin Hebert
A: 

two options:

  1. easy : if Foo were you implemetn an interface you can use a Dynamic proxy to add new functionality.
  2. more work: what you have is an "around" advice of AOP - you can use any of the existing AOP tools to make that possible. Spring Framework can do it for you, if you are using it already.
kartheek
-1 for not being clear, and for bringing Spring into this.
Erick Robertson
A: 

Using a decorator is the right way to go:

Some very similar code to the requirement you have with sockets is here:

http://www.javaspecialists.eu/archive/Issue058.html

Pablojim