4

I get several objects of type Foo from a call to an external API. Locally I want to process those objects with a little added information so I have a subclass FooSon that adds those extra fields. How can I convert all those objects I get, to my new inherited type? Downcasting doesn't seem to be an option because those objects aren't really FooSon.

The only solution I have come up with is creating a convert function that takes the Foo object as an argument and then copies all public/protected values to a new FooSon object that is then returned.

The disadvantages are:

  • Loosing information (private values)
  • Having to adapt the convert function if Foo is ever changed.

Class Foo doesn't implement a copy constructor or clone operator. I have the Foo source code but I would like to avoid changing it in order to keep compatibility with future releases. Nevertheless if it is the only viable alternative I would change the Foo implementation to get what I need.

skaffman
  • 398,947
  • 96
  • 818
  • 769
Omar Kohl
  • 1,372
  • 2
  • 15
  • 32
  • Just to make it clear I haven't designed Foo, and I shouldn't be changing it. It is inside a .jar and I got the source code from the developer repository. Changing Foo would mean dumping the .jar and incorporating the src into my own project. – Omar Kohl Mar 27 '11 at 12:58

5 Answers5

4

FooSon could have a field in it that is a Foo. then just assign the returned value into that field. You could then create methods in Fooson that delegate their calls to the Foo field for the information that you need from the Foo from outside.

MeBigFatGuy
  • 28,272
  • 7
  • 61
  • 66
  • Composition instead of inheritance. I thought about that and it is a little cumbersome to "re-route" all 15 public methods of Foo. Maybe it's the only alternative... – Omar Kohl Mar 27 '11 at 13:02
4

I think decorator pattern should works here:

class Foo implements FooApi {...}

class FooSon implements FooApi {
    private FooApi decoratedFoo;
    private String additional;

    public FooSon(FooApi decoratedFoo) {
        this.decoratedFoo = decoratedFoo;
    }
    ...
}

but you can do this only if you have interface for your Foo object.

lukastymo
  • 26,145
  • 14
  • 53
  • 66
  • I agree that this is a situation where the decorator pattern fits nicely. Unfortunately, as I pointed out, I don't have control over Foo. – Omar Kohl Mar 27 '11 at 15:16
0

Maybe I haven't fully understood the problem, but why instead of subclassing Foo (inheritance) aren't you storing Foo like a field type in FooSon (composition)?

In anycase, if you can't modify access control to Foo type because the objects are defined into an external library, you can't get direct access to private fields(this is exactly the property of a private field). If those private fields can be accessed from getters and setters method, so wrap that methods in your FooSon class.

Heisenbug
  • 38,762
  • 28
  • 132
  • 190
0

Well, as you already found out down casting is not applicable in this situation. I see the following options:

  • The external library provides some factory mechanism you could use to make it instantiate FooSon instead Foo.

  • The recipient wraps Foo objects in FooSon objects, possibly using the delegator pattern.

  • The recipient logically attaches additional information by to Foo objects by using a map with Foo as key.

jmg
  • 7,308
  • 1
  • 18
  • 22
0

You should not downcast, you have no guarantee it will succeed and there are better ways of dealing with this problem. For one you could wrapper the Foo object in another class and delegate the appropriate method calls back to the Foo object.

I suggest you take some time to make sure you understand some basic OO concepts. In particular, google for "composition versus inheritance", this link seems like a decent explanation.

katsharp
  • 2,551
  • 24
  • 27
  • I'm definitely no expert, but I do understand the difference between inheritance and composition. :-D. The reason I wanted to avoid composition is not having to delegate all those methods (lazy programmer, you know...) – Omar Kohl Mar 27 '11 at 13:06
  • 1
    Heh - it may seem like effort, but it is the right thing to do. If you are using a capable IDE you could implement a template do take some of the pain away. I use eclipse, here is an example of the template I would use to quickly delegate the method call to the foo object. foo.${enclosing_method}(${enclosing_method_arguments}) ... and foo.${enclosing_method} when it is a no-args method – katsharp Mar 27 '11 at 13:11
  • You made me search a bit and I found out that with Netbeans (my favourite IDE) you can generate all delegate methods with two mouseclicks :-) – Omar Kohl Mar 27 '11 at 15:13