简体   繁体   中英

How to override/extend an inner class from a subclass?

I want to change how a method of a class executes without overriding the method, and only overriding (or ideally extending) the inner class. Assume that I cannot change the fact that I need to do this (I am modifying an existing open source code base and there would be friction to pulling out classes or whatnot).

public class A {
  static class Thing {
    public int value() { return 10+value2(); }
    public int value2() { return 10; }
  }

  public String toString() {
    Thing t = new Thing();
    return Integer.toString(t.value());
  }
}

public class B extends A {
  static class Thing {
    public int value2() { return 20; }
  }
}

My goal is, by changing only Thing, getting B's toString() to return "30", where currently it will return "20". The ideal would be to change only the method value2 (thus leaving any other methods unchanged), but I don't know if this is possible.

Thanks

I think you need a factory method for this. Consider the following example ( derived from your snippet ):

static class A {
    static class Thing {
        public int value() {
            return 10 + value2();
        }
        public int value2() {
            return 10;
        }
    }
    protected Thing createThing() {
        return new Thing();
    }
    public String toString() {
        return Integer.toString(createThing().value());
    }
}

static class B extends A {
    static class Thing extends A.Thing {
        public int value2() {
            return 20; 
        }
    }
    @Override
    protected Thing createThing() {
        return new Thing(); // creates B.Thing
    }
}

public static void main(String[] args) {
    System.out.println(new B());
}

Output:

30

You should be able to just extend the inner class with Thing extends A.Thing. As long as it's visible in your scope it shouldn't be a problem.

It's not possible by only changing value2. The problem is that 'new' calls aren't dispatched dynamically - the 'new' in toString will always create A::Thing. You could fix this creating a factory : something like this:

public class A {
  static class Thing {
    public int value() { return 10+value2(); }
    public int value2() { return 10; }
  }

  private Thing makeThing() { return new Thing(); }


  public String toString() {
    Thing t = new Thing();
    return Integer.toString(t.value());
  }
}

public class B extends A {
  static class Thing extends A.Thing {
    public int value2() { return 20; }
  }

  private Thing makeThing() { return new Thing(); }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM