开发者

Adding functions to Java class libraries

I'm using a Java class library that is in many ways incomplete: there are many classes that I feel ought to have additional member functions built in. However, I am unsure of the best practice of adding these member functions.

Lets call the insufficient base class A.

class A
{
    public A(/*long arbitrary arguments*/)
    {
        //...
    }

    public A(/*long even more arbitrary arguments*/)
    {
        //...
    }

    public int func()
    {
        return 1;
    }
}

Ideally, I would like to add a function to A. However, I can't do that. My choice is between:

class B extends A
{
    //Implement ALL of A's constructors here

    public int reallyUsefulFunction()
    {
        return func()+1;
    }
}

and

class AddedFuncs
{
    public static int reallyUsefulFunction(A a)
    {
        return a.func()+1;
    }
}

The way I see it, they both have advantages and disadvantages. The first choice gives a cleaner syntax than the second, and is more logical, but has problems: Let's say I have a third class, C, within the class library.

class C
{
    public A func()
    {
        return new A(/*...*/);
    }
}

As I see it, there is no easy way of doing this:

C c;
int use开发者_如何转开发ful = c.func().reallyUsefulFunction();

as the type returned by C.func() is an A, not a B, and you can't down-cast.

So what is the best way of adding a member function to a read-only library class?


Natural and frequent dilemma. Read about the composition vs inheritance alternative. Your second alternative is basically a composition, if we think that the object A is passed in the constructor instead of passing it in each method - that is, we would be using composition to implement a wrapper or decorator pattern.

The issue for class C returning a new instance of class A has no trivial solution, as you guessed, as long as class C decides to take responsability of creating the new instance. This is why one should pause and think before typing a "new" statement inside a class, if there is the possibility that this class will be subclassed. In yout example, it would be nice if you could tell class C what concrete class to return ... but how would it know to create it? Well we could pass him an object who knows how to instantiate an object of class A (or a subclass)... I guess you are enough motivated to read about Factories now, and design patterns in general.

There is no unique best answer, but if want a quick one: I'd make a wrapper, B class does not extend A but has a constructor with A as parameter, it delegates its methods (except the own) to the inside object. When you need to call the method in class C (I'm assuming you cant touch class C), you could write: B b = new B(c.func())


Why not use Composition instead of Inheritance?

class ABetterA {
    private A a;

    public ABetterA() {

    }

    // write wrapper methods calling class' A methods and maybe doing something more
}

This way, you could also mimic multiple inheritance...


You have a third option. You could use Scala (a Java compatible language) and its traits, which are mixins by another name.


Another option similar to Brian's sugestion is to use Aspect Oriented Programming (AOP) tool, such as ApectJ, which let you "inject" additional functionality into existing classes, even binary ones. You either preprocess the library jar to get a new one with enhanced classes ("static weaving") or you can do all of this at runtime when the library classes are loaded (so called "load-time weaving"). You can check this AspectJ example.

Even though AOP is normally used to modify existing methods (before, after or around "advices" = code pieces) you can also introduce new members and methods - check AspectJ's Inter-type declarations.

Of course there is the question whether AspectJ is supported at your limited platform.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜