Ignoring the fact, that in your example you want to inverse the as-is relation (as in "an apple is-a fruit" vs "a fruit is-an apple") - which is pointless to a certain degree.
But lets imagine a case, where you have to make a potate look like an apple. So what you'll do is to carve out all the pulp and put the potato into the apple (I use the fruit example here because with animals it gets a bit messy).
This is either called proxying or wrapping.
Both techniques can be done in java either statically or dynamically.
statically: a Wrapper:
- Create new Class, i.e. VeggiAppleWrapper
- let it extend Apple (so anything it wraps looks like an apple)
- define a constructor that accepts the other type (i.e. Potato)
- implement/override the methods that are common and delegate the calls to the wrapped object
- implement all other methods throwing an UnsupportedOperationException
dynamically: a Proxy:
- you have to define an interface at least for the target type (i.e.
interface Apple
)
- create a proxy instance using Proxy
- use the
Apple
interface in the list of implemented interface
- implement a
MethodInvocationHandler
that does the forwarding for you, similar to the Wrapper, but using Reflection
- cast the proxy to
Apple
Alternatives to using Java's dynamic proxy are code generation libraries such as CGLib or Javaassist that generate a subclass of your target type at runtime, which is basically the same as the wrapper but implemented like the proxy.
In order to just copy the values from animal to the cat instance (as animal is a superclass, some fields should be common), you could use the reflection api as well
for(Field f : Animal.class.getDeclaredFields()) {
f.setAccessible(true)
f.set(cat, f.get(animal));
}
This is just a simple example, without exception handling and without considering the fields of Animal's superclass (getDeclaredFields
only retrieves the field of this class).