28

Here is my problem actually I'm facing now. I have a class, let's say Foo and this class defines a method called getBar that returns a Bar instance. The class Bar is defined inside Foo and and is declared public static final. What I want to do is to define a class MyFoo that extends Foo but I also want to extend Bar with MyBar by adding my own functionalities (methods, properties,etc). I also want getBar to return MyBar.

The problem is Bar is final. Here is an illustration of what I want to do :

public class Foo {

  Bar bar = new Bar();

  public Bar getBar(){
      return bar;
  } 

   ....

   public static final class Bar {

    } 
}

What I want to do is :

public class MyFoo extends Foo {


   public MyBar getBar(){ // here I want to return an instance of MyBar

   }

  public static final class MyBar extends Bar { // That's impossible since Bar is final

  } 
}

How can I achieve that?

[EDIT] I am adding more details to my question. I am actually developing a plugin for Jenkins and after searching, I realize there is a plugin that offers the base functionalities that I want to do, Foo and Bar. I want to custom Foo and Bar, so it can fits my needs. Foo is the main class of the plugin and extends a class called Builder. Foo defines a method called perform which contains all the operations for performing a build. Bar contains operations for configurations purposes and Foo needs Bar to get those informations.

So what I want to do is to extend Foo with MyFoo and add some configurations with MyBar. And as you see, MyFoo will need to get those configuations by calling getBar();

The second thing is I have no control of the instanciation of MyFoo and MyBar

What blocks me, is that I cannot extend Bar. How can I achieve that?

Dimitri
  • 8,122
  • 19
  • 71
  • 128
  • 8
    Since the `final` modifier prevents you from subclassing `Bar`, I'd recommend "wrapping" it. – mre Nov 08 '12 at 17:41
  • If `Bar` is a `final class` it is usually for some good reason, e.g. pehaps because some invariants of `Foo` requires that. So I won't do that, or at least you should precisely understand all the relevant source code, and perhaps rewrite it. – Basile Starynkevitch Nov 08 '12 at 17:42
  • 2
    Ask the developer of `Bar` to make it non-final or use delegation as mre suggests. – Peter Lawrey Nov 08 '12 at 17:43
  • Ideally in such a case, `Bar` would implement an interface `IBar`, with the rest of the app coded against the interface. Using `final` on a simple class that's not completely internal to a design is probably a design smell. (Like on a class returned to clients of an API.) – millimoose Nov 08 '12 at 17:43
  • Thanks for your answers, guys. How can I "wrap" Bar? – Dimitri Nov 08 '12 at 18:08
  • @Dimitri: You can't. Meaning, you can wrap the class (`MyBar` holds and instance of `Bar`, implements the same methods by calling bar, as in: `foo() { return bar.foo(); }`), but that doesn't help you, since you want to be able to return `MyBar` from `MyFoo.getBar()`. Not sure why that was a suggestion... – Dmitri Nov 08 '12 at 19:23

7 Answers7

40

You can't, basically. It looks like the developer who designed Bar intended for it not to be extended - so you can't extend it. You'll need to look for a different design - possibly one which doesn't use inheritance so much... assuming you can't change the existing code, of course.

(It's hard to give more concrete advice without knowing more about the real goal here - the design of the overall system.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Well, I am actually developing a plugin for Jenkins and the thing is Foo and Bar has a lot functionalities that I want to extend. That would prevent me rewrite the same code of Foo and Bar – Dimitri Nov 08 '12 at 18:07
  • 1
    @Dimitri: That doesn't really give us enough information to know whether it would be reasonable to use composition instead of inheritance, for example. – Jon Skeet Nov 08 '12 at 18:08
  • `Foo` and `Bar` were designed deliberately so that you could not extend them. You don't really have an alternative. – Louis Wasserman Nov 08 '12 at 21:56
17

You can't extend a class that is declared final. However you can create an intermediate class, called Wrapper. This Wrapper will basically contain an instance of the original class and provide alternative methods to modify the state of the object according what you want to do.

Of course this will not give access to the private & protected fields of the final class, but you can use its getters and setters methods, combined with the new methods & fields you declared in the Wrapper class to get the result you want to, or something relatively close.

Another solution is not to declare final a class if there is no valid reason to do it.

Mickäel A.
  • 9,012
  • 5
  • 54
  • 71
10

You can't extend a final class - that's the purpose of the final keyword.

However, there are (at least) two work-arounds:

  1. The class is in the Jenkins project, which is open source, so you can just download the project, make the changes you want to the class and re-build the jar
  2. Somewhat of a hack, but you could use a library like Javassist to replace the implementation of the class in memory
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • 2
    Why would someone make a class final? It may sound like a terrible question but I'm new to programming. I was trying to extend the Scanner class (just to see if I could) and I saw it wouldn't work. My friend told me it was because the Scanner class was final. Let's say theoretically it wasn't final and somebody did extend it. What would be the issue since any variables that are changed within the child class doesn't have to change the parent class? Etc. Idk – Adam Staples Jun 08 '14 at 06:36
  • I know it has something to do with the Scanner class being overridden but I wouldn't even know how to overwrite it if it wasn't final and I tried. – Adam Staples Jun 08 '14 at 06:50
5

Probably what you want is a Proxy. It's easy to implement. This is a great article: http://blog.frankel.ch/the-power-of-proxies-in-java

Jacob van Lingen
  • 8,989
  • 7
  • 48
  • 78
idiogo
  • 193
  • 3
  • 5
4

You cannot extend final classes, that is the point of declaring classes final. You can define an interface that both the final class inherit from and a wrapper class that delegates calls to the wrapped final class. The question is then why to make the class final in first place.

antiguru
  • 1,101
  • 11
  • 18
0

For example we cannot add a StringBuffer in the TreeSet Collection, because TreeSet is not child of the Interface Comparable:

public class Main(){
public static void main(String[] args){
   TreeSet treeSetSB = new TreeSet();
   treeSetSB.add(new StringBuffer("A"));  //error, Comparable is not implemented
}

But we can use a wrapper to implement the Comparable:

class myWrap implements Comparable{
    TreeSet treeset;
    public myWrap() {
        this.treeset=new TreeSet<>();

    }
    public TreeSet getTreeset() {
        return treeset;
    }
    public void setTreeset(TreeSet treeset) {
        this.treeset = treeset;
    }
}


public class Main(){
public static void main(String[] args){

   myWrap myWrap =new myWrap();
   TreeSet myTrs  =myWrap.getTreeset();
   myTrs.add("b");   // no error anymore
   myTrs.add("a");
   myTrs.add("A");
   System.out.println(myTrs);
}
Alexis
  • 498
  • 4
  • 13
0

If it implements some interfaces, Decorator Design pattern could solve the Problem.