A weird little problem about handling objects without knowing whatthey are

Discussion in 'Java' started by Tom Anderson, Jul 15, 2008.

  1. Tom Anderson

    Tom Anderson Guest

    Hello!

    I wonder if anyone has any ideas on how or whether i can do something.

    I have an interface a bit like this:

    public interface Machine {
    }

    public interface MachineManager {
    public Machine getByID(String id) ;
    public List<Machine> getAllInRoom(int roomNumber) ;
    public void switchOn(Machine m) ;
    public void switchOff(Machine m) ;
    }

    With a couple of different implementations.

    Now, i know what you're thinking: why aren't switchOn and switchOff
    methods on Machine?

    The reason is because i've told a bit of a lie. I do have a couple of
    classes that are like MachineManager, but in each case, Machine is a
    totally different thing. It's more like:

    public interface FruitManager {
    public Fruit getByID(String id) ;
    public void switchOn(Fruit f) ;
    }

    public interface CloudManager {
    public Cloud getByID(String id) ;
    public void switchOn(Cloud d) ;
    }

    Fruit and Cloud do not share any common base type below Object, and thus
    there's no type that has a switchOn() that i could use for both. They're
    both third-party library classes, so i can't do anything about this.

    But still, i want to be able to write client code that gets things by ID
    or room number, and then switches them on and off - without knowing what
    they are.

    I also want to ensure that the managers are only ever fed instances of the
    right kind of object. If someone feeds a Fruit to a CloudManager, there'll
    be hell to pay.

    I think there's no way to do this using polymorphism. Is there any way to
    do it using generics? I haven't been able to come up with anything, but i
    feel like i should be able to say something like:

    ThingManager<T> mgr = ... ;
    T thing = mgr.getById("cirrusberry") ;
    mgr.switchOn(thing) ;

    But without having to make the calling code generic, and supply a type
    parameter to that. To sort of have a floating type variable. Does that
    make any sense? Can i use a wildcard here somewhere?

    If there's no typological solution, i can see two options.

    Option zero is just to use Object for the things, have no static type
    safety, and rely on dynamic safety. It'll work, but it's not exactly
    pretty.

    A slightly better option is to wrap the things inside a polymorphic
    wrapper:

    public interface Manageable {
    }

    public class FruitWrapper implements Manageable {
    // ...
    }

    public class CloudWrapper implements Manageable {
    // ...
    }

    public interface Manager {
    public Manageable getByID(String id) ;
    public void switchOn(Manageable m) ;
    }

    This gives me a measure of type safety, but doesn't actually stop someone
    passing a CloudWrapper to a FruitManager. Although in this case, i could
    dispense with the switchOn method in Manager, and implement it as an
    instance method in Manageable, so maybe this problem would evaporate.

    The second is to hide the objects altogether, and have an interface that
    looks like:

    public interface Manager {
    public void switchOnByID(String id) ;
    public void switchOnAllInRoom(int roomNumber) ;
    }

    Or possibly, avoiding massive duplication:

    public class Selector {
    public Selector(String ID) ;
    public Selector(int roomNumber) ;
    }

    public interface Manager {
    public void switchOn(Selector s) ;
    }

    Which would work, but doesn't excite me very much.

    Any ideas?

    tom

    PS Fruit and Cloud are actually Elements, from the W3C DOM and DOM4J
    packages respectively.

    PPS DOM4J has dual-interfaced objects, which are both DOM4J Elements and
    W3C Elements. That might be a solution, but i'd like to avoid that if
    possible, since the object creation is happening in another third-party
    library, and i'd have to fiddle with that!

    --
    As Emiliano Zapata supposedly said, "Better to die on your feet than
    live on your knees." And years after he died, Marlon Brando played him
    in a movie. So just think, if you unionize, Marlon Brando might play
    YOU in a movie. Even though he's dead. -- ChrisV82
     
    Tom Anderson, Jul 15, 2008
    #1
    1. Advertising

  2. Tom Anderson

    Mark Space Guest

    Re: A weird little problem about handling objects without knowingwhat they are

    Tom Anderson wrote:

    > A slightly better option is to wrap the things inside a polymorphic

    wrapper:

    I did like this best. If I understand what you are trying to do, you're
    having problems like this:


    class Wrapper {}
    class Cloud extends Wrapper {}
    class Fruit extends Wrapper {}

    interface Manager{
    void switchOn( Wrapper w );
    }

    class CloudManager implements Manager {
    @Override
    public void switchOn( Cloud c ) {}
    }

    which almost works, but fails because the switchOn method in
    CloudManager doesn't actually over ride the switchOn method in the
    interface Manager. Not to worry, there is a solution:


    class Wrapper {}
    class Cloud extends Wrapper {}
    class Fruit extends Wrapper {}

    interface Manager<WRAPPER extends Wrapper> {
    void switchOn( WRAPPER w );
    }

    class CloudManager implements Manager<Cloud> {
    @Override
    public void switchOn( Cloud c ) {}
    }


    I can't promise that this construct won't bite you in some other way,
    but it does compile, and I think it gets you what you want.

    I wish I could take credit for this idea, but I can't. Our local guru
    Stefan Ram is the author of this idea.

    <http://groups.google.com/group/comp.lang.java.programmer/browse_thread/thread/c651aaf98394214b?fwc=2>
     
    Mark Space, Jul 15, 2008
    #2
    1. Advertising

  3. Re: A weird little problem about handling objects without knowingwhat they are

    Tom Anderson wrote:
    > Hello!
    >
    > I wonder if anyone has any ideas on how or whether i can do something.
    >
    > I have an interface a bit like this:
    >
    > public interface Machine {
    > }
    >
    > public interface MachineManager {
    > public Machine getByID(String id) ;
    > public List<Machine> getAllInRoom(int roomNumber) ;
    > public void switchOn(Machine m) ;
    > public void switchOff(Machine m) ;
    > }
    >
    > With a couple of different implementations.
    >
    > Now, i know what you're thinking: why aren't switchOn and switchOff
    > methods on Machine?
    >
    > The reason is because i've told a bit of a lie. I do have a couple of
    > classes that are like MachineManager, but in each case, Machine is a
    > totally different thing. It's more like:
    >
    > public interface FruitManager {
    > public Fruit getByID(String id) ;
    > public void switchOn(Fruit f) ;
    > }
    >
    > public interface CloudManager {
    > public Cloud getByID(String id) ;
    > public void switchOn(Cloud d) ;
    > }
    >
    > Fruit and Cloud do not share any common base type below Object, and thus
    > there's no type that has a switchOn() that i could use for both. They're
    > both third-party library classes, so i can't do anything about this.
    >
    > But still, i want to be able to write client code that gets things by ID
    > or room number, and then switches them on and off - without knowing what
    > they are.
    >
    > I also want to ensure that the managers are only ever fed instances of
    > the right kind of object. If someone feeds a Fruit to a CloudManager,
    > there'll be hell to pay.
    >
    > I think there's no way to do this using polymorphism. Is there any way
    > to do it using generics? I haven't been able to come up with anything,
    > but i feel like i should be able to say something like:
    >
    > ThingManager<T> mgr = ... ;
    > T thing = mgr.getById("cirrusberry") ;
    > mgr.switchOn(thing) ;
    >
    > But without having to make the calling code generic, and supply a type
    > parameter to that. To sort of have a floating type variable. Does that
    > make any sense? Can i use a wildcard here somewhere?
    >
    > If there's no typological solution, i can see two options.
    >
    > Option zero is just to use Object for the things, have no static type
    > safety, and rely on dynamic safety. It'll work, but it's not exactly
    > pretty.
    >
    > A slightly better option is to wrap the things inside a polymorphic
    > wrapper:
    >
    > public interface Manageable {
    > }
    >
    > public class FruitWrapper implements Manageable {
    > // ...
    > }
    >
    > public class CloudWrapper implements Manageable {
    > // ...
    > }
    >
    > public interface Manager {
    > public Manageable getByID(String id) ;
    > public void switchOn(Manageable m) ;
    > }
    >
    > This gives me a measure of type safety, but doesn't actually stop
    > someone passing a CloudWrapper to a FruitManager. Although in this case,
    > i could dispense with the switchOn method in Manager, and implement it
    > as an instance method in Manageable, so maybe this problem would evaporate.
    >
    > The second is to hide the objects altogether, and have an interface that
    > looks like:
    >
    > public interface Manager {
    > public void switchOnByID(String id) ;
    > public void switchOnAllInRoom(int roomNumber) ;
    > }
    >
    > Or possibly, avoiding massive duplication:
    >
    > public class Selector {
    > public Selector(String ID) ;
    > public Selector(int roomNumber) ;
    > }
    >
    > public interface Manager {
    > public void switchOn(Selector s) ;
    > }
    >
    > Which would work, but doesn't excite me very much.
    >
    > Any ideas?
    >
    > tom
    >
    > PS Fruit and Cloud are actually Elements, from the W3C DOM and DOM4J
    > packages respectively.
    >
    > PPS DOM4J has dual-interfaced objects, which are both DOM4J Elements and
    > W3C Elements. That might be a solution, but i'd like to avoid that if
    > possible, since the object creation is happening in another third-party
    > library, and i'd have to fiddle with that!
    >


    From what I understand - you have objects that have same interface (not
    java interface, but interface in the sense of operations supported by an
    object) but different runtime types and static/compile time type
    checking is messing things up. I suppose changing the type of object at
    runtime is just about as good (or bad) as using reflection.

    The wrapper is a good way to go about this.

    Alternatively (and only slightly differently), you could use
    java.lang.reflect.Proxy . You could write a common getByID
    implementation for the Manager -

    Manageable
    {
    void switchSelfOf() ;
    void swithSelfOff() ;
    }
    Manager
    {
    Manageable getByID(String id) ;
    // .. other methods ..
    }

    abstract class AbstractManager implements Manager
    {
    public Manageable getByID(String id)
    {
    Object iHaveNoCompileTimeType = getUntypedObjectByID(id) ;
    // now convert this to a Manageable using proxy
    // which, in the end, uses reflection ..
    }
    protected abstract Object getUntypedObjectByID(String id) ;
    }

    For your case, however, I would suggest using a java.lang.reflect.Proxy
    to do a type conversion since the interfaces (the ones you are using)
    are, I suppose, identical.

    So a method like

    w3c.Element convertFromDOM4JToW3C(dom4j.Element element)
    {
    // wrap up element into a proxy .. which will effectively
    // change the runtime type of "element" object from
    // dom4j.Element to w3c.Element
    }


    should be sufficient to convert between the two types.


    Abhijat
     
    Abhijat Vatsyayan, Jul 16, 2008
    #3
  4. Tom Anderson

    Daniel Pitts Guest

    Re: A weird little problem about handling objects without knowingwhat they are

    Tom Anderson wrote:
    > Hello!
    >
    > I wonder if anyone has any ideas on how or whether i can do something.

    [...snip...]
    >
    > A slightly better option is to wrap the things inside a polymorphic
    > wrapper:
    >
    > public interface Manageable {
    > }
    >
    > public class FruitWrapper implements Manageable {
    > // ...
    > }
    >
    > public class CloudWrapper implements Manageable {
    > // ...
    > }


    This seems like the best idea. If you want to find the Pattern, I
    believe its called the Adapter Pattern. It actually buys you at *least*
    three things in this case.

    1. Type safety. If you require a FruitWrapper, you can ask for it directly.

    public void actOnFruit(FruitWrapper wrapper) {}

    2. Polymorphism. (For your use case especially)

    3. Encapsulation. Today FruitWrapper wraps an Element. Tomorrow it
    could wrap something else altogether, or not even be a Wrapper at all.

    There are other benefits to using this pattern, but I would say those
    are the biggest ones.

    Hope this helps,
    Daniel.

    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
     
    Daniel Pitts, Jul 20, 2008
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Christopher
    Replies:
    2
    Views:
    536
    Christopher
    Feb 16, 2004
  2. CodeMotion
    Replies:
    0
    Views:
    571
    CodeMotion
    Jul 3, 2003
  3. ThaDoctor
    Replies:
    3
    Views:
    403
    Alan Woodland
    Sep 28, 2007
  4. Christof Warlich
    Replies:
    4
    Views:
    320
    Christof Warlich
    Aug 9, 2008
  5. Replies:
    4
    Views:
    141
Loading...

Share This Page