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

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(); }
}

Related

How can each derived class can have its own static value, while sharing the same base method in Java?

class Base {
Base() {
System.out.println("Base Constructor");
}
}
class Derived1 extends Base {
private static String pattern = "a+b+";
Derived1() {
super();
System.out.println("Derived 1 Constructor");
}
public static boolean doesMatch(String v) {
return v.matches(pattern);
}
}
class Derived2 extends Base {
private static String pattern = "c+";
Derived2() {
super();
System.out.println("Derived 2 Constructor");
}
public static boolean doesMatch(String v) {
return v.matches(pattern);
}
}
class Builder {
public static Base baseFromString(String v) throws Exception {
if (Derived1.doesMatch(v)) return new Derived1();
if (Derived2.doesMatch(v)) return new Derived2();
throw new Exception("Could not match " + v + " to any derived type.");
}
}
class Test {
public static void main(String[] args) throws Exception {
Base b = Builder.baseFromString("aaab");
}
}
The code above has a primary problem I want to solve:
The doesMatch method is repeated code for the two derived classes. I'd like to move it to the base class, but then it won't be able to access the pattern member. How do I structure my code better so that each derived class can have its own static pattern, while they all share the same base doesMatch method?
I've tried messing around with abstract classes and interfaces, but I couldn't get anything to work. I am fine with those types of solutions as long as there is a hierarchy where the derived classes either extend or implement the base class.
Secondary question (from original post)
I might want to add several more derived classes. I'd like to not have to update the baseFromString method with another if every time I extend the base class. Is this something that can be solved with polymorphism?
A functional technique (Java 9+), but there is some performance overhead:
class Base {
Base() {
System.out.println("Base Constructor");
}
}
class Derived1 extends Base {
Derived1() {
super();
System.out.println("Derived 1 Constructor");
}
}
class Derived2 extends Base {
Derived2() {
super();
System.out.println("Derived 2 Constructor");
}
}
interface NewBase {
Base create();
}
final class Pattern {
final private String pattern;
final private NewBase newBase;
public Pattern(String pattern, NewBase newBase) {
this.pattern = pattern;
this.newBase = newBase;
}
public String getPattern() {
return pattern;
}
public NewBase getNewBase() {
return newBase;
}
}
class Builder {
final private static List<Pattern> newObjects = new ArrayList<>();
private static void addPattern(String pattern, NewBase newObject) {
newObjects.add(new Pattern(pattern, newObject));
}
static {
addPattern("a+b+", Derived1::new);
addPattern("c+", Derived2::new);
}
public static Base baseFromString(String v) throws Exception {
for (Pattern p : newObjects) {
if (v.matches(p.getPattern()))
return p.getNewBase().create();
}
throw new Exception("Could not match " + v + " to any derived type.");
}
}
Just update the static Builder initializer to call the addPattern for new patterns and derived classes.
You can't do that, at least not with static members. The problem is that static members cannot be overridden.
public class Driver {
public static void main(String args[]) {
Derived aDerived = new Derived();
aDerived.print(); // prints "Value is 5", not "Value is 10"
}
}
public class Base {
protected static final int VALUE = 5;
public Base() {}
protected void print() {
System.out.println("Value is " + VALUE);
}
}
public class Derived extends Base {
protected static final int VALUE = 10; // does not override base Value
public Derived() {}
}
Each subclass can have its own value, and they would all inherit print(). But it doesn't do what you want because print() will always reference Base.VALUE even in the inherited Derived.print().
So, static doesn't work. I assume that you feel the pattern member needs to be static because there only needs to be one copy of the pattern value for the entire class. That one copy part should have tipped you off to a handy little design pattern: the singleton pattern!
public class Driver {
public static void main(String args[]) {
Derived aDerived = new Derived();
aDerived.print(); // prints "Value is 10"
}
}
public class Base {
protected Value val = Value.getInstance();
public Base() {}
protected void print() {
System.out.println("Value is " + val.value());
}
}
public class Derived extends Base {
public Derived() { val = DerivedValue.getInstance(); }
}
public class Value {
private int value = 5;
public int value() { return value; }
private static Value instance = new Value();
protected Value() {}
public static Value getInstance() { return instance; }
}
public class DerivedValue extends Value {
private int value = 10;
public int value() { return value; }
private static DerivedValue instance = new DerivedValue();
private DerivedValue() {}
public static DerivedValue getInstance() { return instance; }
}
There's a lot more code in this version, but now there is only one copy of the two different values used.
Note: Below is how you can make the value members final. You'll have to set up your packages appropriately so the protected Base(Value v) constructor is only visible to the Derived class.
public class Base {
protected final Value val;
public Base() { val = Value.getInstance(); }
protected Base(Value v) { val = v; }
protected void print() {
System.out.println("Value is " + val.value());
}
}
public class Derived extends Base {
public Derived() { super(DerivedValue.getInstance()); }
}

Decorator pattern with varying contract

In the decorator pattern, I'm confused about how to use a decorator method. I have learned that the decorator pattern is used to add functions to base-class. But I could call only the outermost decorator's method, so how should I use inner-decorator's method, if it not mentioned in interface. I'm not good at English, so I write code to demonstrate my question.
public class OrderSystem {
public static void main(String[] args) {
Pancakes pancakes = new MixedPancakes();
pancakes = new Ham(pancakes);
((Ham) pancakes).hamState(); // call hamState
pancakes = new Egg(pancakes);
((Egg) pancakes).eggState();
// i can't call hamState() there because it not belong to Egg
Pancakes pancakes1 = new Ham(new Egg(new FlourPancakes()));
// similarly, i can't use eggState() there.
System.out.println("订单:" + pancakes1.getDescription());
System.out.println("价格:" + pancakes1.cost());
}
}
interface Pancakes {
public abstract String getDescription();
public abstract int cost();
}
abstract class Seasoning implements Pancakes {
#Override
public abstract String getDescription();
}
class Ham extends Seasoning {
Pancakes pancakes;
public Ham(Pancakes pancakes) {
this.pancakes = pancakes;
}
#Override
public int cost() {
return pancakes.cost() + 2;
}
#Override
public String getDescription() {
return pancakes.getDescription() + "+火腿";
}
public void hamState() {
System.out.println("火腿切碎");
}
}
class Egg extends Seasoning {
Pancakes pancakes;
public Egg(Pancakes pancakes) {
this.pancakes = pancakes;
}
#Override
public int cost() {
return pancakes.cost() + 1;
}
#Override
public String getDescription() {
return pancakes.getDescription() + "+鸡蛋";
}
public void eggState() {
System.out.println("鸡蛋打碎");
}
}
class MixedPancakes implements Pancakes {
#Override
public String getDescription() {
return "五谷杂粮煎饼";
}
#Override
public int cost() {
return 6;
}
}
class FlourPancakes implements Pancakes {
#Override
public String getDescription() {
return "白面煎饼";
}
#Override
public int cost() {
return 5;
}
}
As I asked in annotation, when a decorator was wrapped with another, only the method that declared in interface (like cost() and getDescription()) will work, and the other method won't be called anymore. I thought if I create a soldier, if I use a gun decorate he will be shoot()--the gun's function. If I decorate him with sword tomorrow, he will not only could shoot() but also cut()--the sword's function. Can I achieve it with decorator pattern?
I'm sorry for any misunderstandings and thanks for your help.
As people mentioned in comments in your question, the decorator pattern is not used exactly like that.
Using your soldier example, the decorator would work like this:
public abstract class Soldier {
public abstract void attack();
}
public abstract class SoldierDecorator extends Soldier {
protected Soldier soldier;
public SoldierDecorator(Soldier soldier) {
this.soldier = soldier;
}
#Override
public abstract void attack();
}
and then
public class SoldierWithGun extends SoldierDecorator {
public SoldierWithGun(Soldier soldier) {
super(soldier);
}
#Override
public void attack() {
soldier.attack();
shootWithTheGun();
}
private void shootWithTheGun() {
System.out.println("Shooting with the gun...");
}
}
public class SoldierWithSword extends SoldierDecorator {
public SoldierWithSword(Soldier soldier) {
super(soldier);
}
#Override
public void attack() {
soldier.attack();
cutWithSword();
}
private void cutWithSword() {
System.out.println("Cutting with the sword...");
}
}
Passing your soldier from decorator to decorator would enhance their attack;
Now to add behavior/methods, you can use plain old inheritance.
You could add behavior by extending classes, BaseSoldier can walk but SoldierWithGun extends BaseSoldier, adds a method to shoot besides walking.
You can use interfaces to ensure that certain functionalities are available in classes that implement them.
It is not exactly "decorating" as you want, but I think this is the way to go for what you want to do.

When creating a builder with a superclass, parent cannot return instance of child class [duplicate]

This question already has answers here:
Subclassing a Java Builder class
(10 answers)
Closed 6 years ago.
If I am using the builder pattern to configure new objects I may have two classes like Game and HockeyGame (shown below). When I want to create a new HockeyGame, I get it's builder and start calling methods to configure the object as needed.
The problem I am running into is shown in the main function. Once I call one method from the super class it returns as an intance of Game.Builder, and I can no longer call any method from the child class.
What is the best way to deal with this?
Main.java
class Main {
public static void main(String[] args){
HockeyGame hg = new HockeyGame.Builder()
.setScore(5)
.setTimeLimit(3600)
//--------------------------------------------------------------------
.setIceTemperature(-5) // Error! Cannot call setIceTempurature() on
// an instance of Game.Builder
//--------------------------------------------------------------------
.build();
}
}
Game.java
public class Game{
int score;
int timeLimit;
public Game(int score, int timeLimit) {
this.score = score;
this.timeLimit = timeLimit;
}
public static class Builder {
int score;
int timeLimit;
public Builder setScore(int score) {
this.score = score;
return this;
}
public Builder setTimeLimit(int timeLimit) {
this.timeLimit = timeLimit;
return this;
}
public Game build() {
return new Game(score, timeLimit);
}
}
}
HockeyGame.java
public class HockeyGame extends Game {
float iceTemperature;
public HockeyGame(int score, int timeLimit, float iceTemperature) {
super(score, timeLimit);
this.iceTemperature = iceTemperature;
}
public static class Builder extends Game.Builder {
float iceTemperature;
public HockeyGame.Buidler setIceTemperature(float iceTemperature) {
this.iceTemperature = iceTemperature;
return this;
}
public HockeyGame build(){
return new HockeyGame(score, timeLimit, iceTemperature);
}
}
}
Thanks.
You need to use the getThis() trick that is prevalent in much fluent API code.
First you need to make your Game.Builder generic in itself:
public static class Builder<B extends Builder<B>>
Then you add a getThis() method:
public B getThis() {
return (B) this;
}
Now you change your setters to return a B and return getThis() rather than this:
public B setTimeLimit(int timeLimit) {
//...
return getThis();
}
Your extension class also needs to be generic, in itself:
public static class Builder<B extends Builder<B>> extends Game.Builder<B>
Now you can use the code, and it will "remember" the intended type:
HockeyGame hockeyGame = new HockeyGame.Builder<>().setScore(10)
.setTimeLimit(20)
.setIceTemperature(-1)
.build();
This final code looks something like:
public class Game {
private final int score;
private final int timeLimit;
private Game(final Builder<?> builder) {
this.score = builder.score;
this.timeLimit = builder.timeLimit;
}
public static class Builder<B extends Builder<B>> {
private int score;
private int timeLimit;
public B setScore(int score) {
this.score = score;
return getThis();
}
public B setTimeLimit(int timeLimit) {
this.timeLimit = timeLimit;
return getThis();
}
protected B getThis() {
return (B) this;
}
public Game build() {
return new Game(this);
}
}
}
public class HockeyGame extends Game {
private final float iceTemperature;
private HockeyGame(final Builder<?> builder) {
super(builder);
this.iceTemperature = builder.iceTemperature;
}
public static class Builder<B extends Builder<B>> extends Game.Builder<B> {
private float iceTemperature;
public B setIceTemperature(float iceTemperature) {
this.iceTemperature = iceTemperature;
return getThis();
}
#Override
public HockeyGame build() {
return new HockeyGame(this);
}
}
}
N.B: I have made the fields private final and also the main type constructors - this forces people to use the Builder. Also, the constructor can take a Builder<?> and copy the variable from there - this tidies the code a little.
The actual hack is, as you may have noticed, here:
public B getThis() {
return (B) this;
}
Here, we force a cast of the Builder to its generic type - this allows us to change the return type of the method dependant upon the specific instance being used. The issue is, if you declare a new Builder something like the following:
public static class FootballGame extends Game {
private FootballGame(final Builder<?> builder) {
super(builder);
}
public static class Builder<B extends HockeyGame.Builder<B>> extends Game.Builder<B> {
float iceTemperature;
#Override
public FootballGame build() {
return new FootballGame(this);
}
}
}
This this will blow up at runtime with a ClassCastException. But the setter method will return a HockeyGame.Builder rather than FootballGame.Builder so the issue should be obvious.
Try something like this
You explicitely cast it back to a HockeyGame.Builder object and work with its own method(s) on it.
The problem you had is that setTimeLimit returns a Builder object (mother class) and so you can not use the child methods on it.
HockeyGame hg = ((HockeyGame.Builder)(new HockeyGame.Builder().setScore(5)
.setTimeLimit(3600)))
.setIceTemperature(-5)
.build();
Also, setIceTemparature should return a HockeyGame.Builder object to be able to build on it.
public Builder setIceTemperature(float iceTemperature) {
this.iceTemperature = iceTemperature;
return this;
}

Is there a way in Java to call a different hashCode() for an interface representation of an object

I've been dealing with a domain issue where I have classes that implement a common interface and I want to be able to get hashes from these objects differently depending on if the object is accessed as an interface or as a concrete class instance. Basically what I want is the following:
public class A implements Bar{
#Override
public int hashCode(){ return 1;}
#Override
public int Bar.hashCode(){ return 123;}
}
public class B implements Bar{
#Override
public int hashCode(){ return 1;}
#Override
public int Bar.hashCode(){ return 123;}
}
public class C implements Bar{
#Override
public int hashCode(){ return 1;}
#Override
public int Bar.hashCode(){ return 123;}
}
Bar interfaceObject = new A();
interfaceObject.hashCode(); //return 123
Bar aObject = new A();
aObject.hashCode();// return 1
As far as I know there isn't a way to do this, and I can think of lots of reasons why this could cause issues, but I wanted to ask those smarter than I if they had any nice ways of doing this outside of making the interface have a function like public int getCustomHashCodeForJustThisInterface(). I like being able to use these objects in hashMaps without having to jump through hoops, but with their current implementation of hashCode they would break, since these objects can have multiple views of their identity depending on how they are used, and I don't want to change their base implementation of hashCode;
You can't do that, because Java does not support non-polymorphic instance methods (static methods are not polymorphic, as the previous answer showed).
What you can do is to make your classes not directly implement Bar, but another interface (e.g. BarProvider) with a toBar() or getBar() method, which returns a custom object of type Bar, which behaves as you want.
public class A implements BarProvider{
#Override
public int hashCode(){ return 1;}
#Override
public Bar toBar() {
return new Bar() {
#Override
public int hashCode() { return 123; }
};
}
}
A aObject = new A();
interfaceObject.hashCode(); //return 1;
Bar interfaceObject = aObject.toBar();
interfaceObject.hashCode(); // return 123
Several improvements are possible, such as having the Bar object stored as a final field (to avoid multiple initializations), and having a reverse reference that allows you to get back from the Bar to its BarProvider.
Another possibility is to use an external provider, that makes your computations
public class A implements Bar{
#Override
public int hashCode(){ return 1;}
}
public final class BarHasher implements Hasher<Bar> }
#Override
public int hashFor(Bar object) { return 123; }
}
A aObject = new A();
interfaceObject.hashCode(); //return 1;
BarHasher.hashFor(aObject); // return 123
or a static method that calls some other method
public class A implements Bar{
#Override
public int hashCode(){ return 1;}
#Override
public int hashAsBar() { return 123; }
}
public interface BarHasher implements Hasher<Bar> {
#Override
public int hashFor(Bar object) { return object.hashAsBar(); }
}
A aObject = new A();
interfaceObject.hashCode(); //return 1;
BarHasher.hashFor(aObject); // return 123
In case you don't know it, what you're trying to do is possible (and it's the default behavior) in C++ (you must declare methods as virtual to have the same behavior as Java) and in C# (but you will have a warning, unless you use the modifier new on the overriding method)
There's no way to do this that I know of.
Here's something you can do that you may not have known of (I'm not suggesting this is a good idea):
package com.sandbox;
import java.io.IOException;
public class Sandbox {
public static void main(String[] args) throws IOException {
A.speak();
B.speak();
A a = new A();
a.speak(); //my ide rightly gives a warning here. static function accessed through instance
A b = new B();
b.speak(); //my ide rightly gives a warning here. static function accessed through instance
}
public static class A {
public static void speak() {
System.out.println("A");
}
}
public static class B extends A {
public static void speak() {
System.out.println("B");
}
}
}
This will print:
A
B
A
A
Just to reiterate: This is NOT a good idea. I'm just letting you know for educational purposes.
It's easy to invoke different methods based on the declared type of a variable. That's called overriding, and here's an example of it:
public class Example {
public static void main(String[] argv) throws Exception {
Integer v1 = 12;
Number v2 = v1;
System.out.println(v1.hashCode() + " -> " + new KeyWrapper(v1).hashCode());
System.out.println(v2.hashCode() + " -> " + new KeyWrapper(v2).hashCode());
}
private static class KeyWrapper {
private Object obj;
private int hash;
public KeyWrapper(Integer v) {
this.hash = v.hashCode() * 3;
}
public KeyWrapper(Number v) {
this.hash = v.hashCode() * 5;
}
#Override
public int hashCode() {
return hash;
}
}
}
When you run this, you get the following output:
12 -> 36
12 -> 60
Why this is a bad idea is that you can't implement equals() in in a way that preserves its contract (which is that two equal objects must have equal hashcodes). At compile-time you have information about how the values are referenced, but at runtime you only know what they are.
That said, if you want to use different hashcode calculations for objects that do implement an interface, versus those that don't, you can write a KeyWrapper that uses instanceof.
public class Example {
public static void main(String[] argv) throws Exception {
Integer v1 = 12;
String v2 = "foo";
System.out.println(v1.hashCode() + " -> " + new KeyWrapper(v1).hashCode());
System.out.println(v2.hashCode() + " -> " + new KeyWrapper(v2).hashCode());
}
private static class KeyWrapper {
private Object wrapped;
public KeyWrapper(Object obj) {
this.wrapped = obj;
}
#Override
public boolean equals(Object obj) {
return wrapped.equals(obj);
}
#Override
public int hashCode() {
return (wrapped instanceof Number) ? wrapped.hashCode() * 3 : wrapped.hashCode() * 5;
}
}
}
This, of course, doesn't care about the declared type of the variable, only its actual type.

Child Instantiate from parent class

It is possiable to instantiate child object from parent class without child class name.
For example, I have next classes:
public class A {
protected int a;
public A1() {
a = 0;
}
public int getA() {
return a;
}
public static A getObject() {
// some code which I need to write
}
}
public class A1 extends A {
public A1() {
a = 5;
}
}
public class A2 extends A {
public A2() {
a = 10;
}
}
Usage example:
A a = A1.getObject();
a.getA(); // return 5
a = A2.getObject();
a.getA(); // return 10
a = A.getObject();
a.getA(); // return 0
A1, A2 it is not all child classes. There are may be unlimited numbers.
How can I write getObject() method to it creates A class childs instanses.
PS:
I just need to initialize child class object, but there are large amounts of child classes and I would not to call "new" for all of them and I would not to write static method to initialize it, also, all childs have same constructors. It is big lack that I can't create child instance from parent.
When you write A a = A1.getObject(),
you do use child classname (A1).
So a) your question is misleading and
b) why can't you just write A a = new A1()?
If you want to write A1.getObject(), then you can redefine getObject() in class A1:
public class A1 extends A {
public static A getObject() {
return new A1();
}
}
Without redefining, there is no way to declare getObject() in class A so that it return objects different classes because A a = A1.getObject() would compile to A a = A.getObject().
class A
{
protected int a;
public A()
{
a = 0;
}
public int getA()
{
return a;
}
public static A getObject(Class c) throws Exception
{
A obj = (A)c.newInstance();
return obj;
}
}
class A1 extends A
{
public A1()
{
a = 5;
}
}
class A2 extends A
{
public A2()
{
a = 10;
}
}
class Test{
public static void main(String args[]) throws Exception
{
A a = A1.getObject(A1.class);
System.out.println(a.getA()); // return 5
a = A2.getObject(A2.class);
System.out.println(a.getA()); // return 10
a = A.getObject(A.class);
System.out.println(a.getA()); // return 0
}
}

Categories