How to wrap class in java and save interface?

12,338

Solution 1

Basically, there are two ways. First one is to extend the base class:

public class MySubClass extends MyClass {
     private MyType1 field1;
     private MyType2 field2;
....

The second option is to use composition:

public class MySubClass implements myInterface1, myInterface2 {
      private MyClass delegate;
      private MyType1 field1;
      private MyType2 field2;

      // for all methods in myInterface1, myInterface2
      public SomeType method1() {
         return delegate.method1();
      }
      ... 
}

The second option is recommended by many Java Gurus:

Josh Bloch's book Effective Java 2nd Edition

  • Item 16: Favor composition over inheritance
  • Item 17: Design and document for inheritance or else prohibit it

Good object-oriented design is not about liberally extending existing classes. Your first instinct should be to compose instead.

See also http://en.wikipedia.org/wiki/Composition_over_inheritance

Composition over inheritance can simplify the initial design of Business Domain classes and provide a more stable business domain in the long term. Its advantage over inheritance is a more thorough isolation of interests than can be described by a hierarchy of descendant classes. Additionally, inheritance models are often contrived during the definition of business domain classes in order to make sense of the information in the problem domain and do not necessarily reflect the true relationship of various system objects.

P.S.: auto-generating code for composition is supported by some of modern IDEs

Solution 2

Don't wrap, just subclass:

class MySubClass extends MyClass {
    MyType1 field1;
    MyType2 field2;
    ...

Solution 3

Assume you can't extend MyClass and you want to be able to use MyWrapClass as type myInterface1 or myInterface2. You can do the following:

MyWrapClass implement myInterface1, myInterface2,...{
   MyClass myClass=new MyClass(...);
   MyType1 field1;
   MyType2 field2;

   methodInInterface1 () {
      myClass.methodInInterface1 ()
   }

   ....

You delegate all methods implementation in myInterface1 and myInterface2 to MyClass. I believe this is called Composition.

Solution 4

Sounds like a problem proxy might solve: http://docs.oracle.com/javase/1.5.0/docs/guide/reflection/proxy.html

Be warned, it's slow (uses reflection)

Solution 5

Assuming you can't extend MyClass, then no there is no other way you can have MyWrapClass and use it like MyClass. For example, it has happened to me to have to implement Map in order to wrap an actual map. It has many functions and every one of them must be implemented that you intend to use. There's a little leeway here, in that if you're not planning to pass it to a a function you didn't write, you can add all required methods and implement only the ones you need. Though more often than not that isn't the case.

Alternatively, you could write a dummy class which implements all methods of the interfaces calling the wrapper. Then you could override this class with your own implementation, allowing you to recycle a wrapper class without having to implement all the methods each time.

Share:
12,338
user710818
Author by

user710818

Updated on June 03, 2022

Comments

  • user710818
    user710818 about 2 years

    I have class like:

    MyClass extends MyAbstractClass implement myInterface1, myInterface2,...
    

    I need create new class with additional fields:

    MyType1 field1;
    MyType2 field2;
    .......
    

    Seems that correct create new class that will wrap MyClass like:

    MyWrapClass {
     MyClass myClass=new MyClass(...);
     MyType1 field1;
     MyType2 field2;
     .....
    

    But MyWrapClass used as type myInterface1 or myInterface2!

    So question is: should I declare all methods that are needed for interfaces myInterface1, myInterface2 in MyWrapClass ? Or exists another way? Thanks.