java – I want to replace the member variables of the inherited class

Question: Question:

Is it possible to briefly describe the following in Java?
This is a naive question, but I hope you can answer it if you have any customs.
Thank you.

class A {
  B b;
  A() {
    this.b = new B();
  }
  // 以下、b を使ったメソッドなど
}

class B {}


class A' extends A {
  // b を使ったメソッドの動作はそのままに b を B' のインスタンスとしたい
}

class B' extends B {}

I thought of the following code.
In the first place, an instance of class B is not created for a member of class A, and a member variable is added by A'that inherits class A.
Of course, if you want to take advantage of the B'extended implementation, you need to cast b with B'.

class A {
  B b;
  A() {
  }
  // 以下、b を使ったメソッドなど
}

class B {}


class A' extends A {
  A'() {
    this.b = new B'();
  }
  // b を使ったメソッドの動作はそのまま
  // B' で拡張された実装を利用する場合は b を B' でキャストする
}

class B' extends B {}

Answer: Answer:

First of all, it is better to change the code of the question a little and provide a protected constructor that specifies the contents of the variable, and do as follows.

Q2322_1.java

class A {
  private final B b;

  protected A( B b) {
    this.b = b;
  }

  public A() {
    this( new B());
  }

  public B getB() { return b; }
}

class B {}

class A_Dash extends A {
  public A_Dash() {
    super( new B_Dash());
  }

  @Override
  public B_Dash getB() { return (B_Dash)super.getB(); }
}

class B_Dash extends B {
  public String getDashness() { return "daaaaaah.";}
}

public class Q2322_1 {
  public static void main(String argv[]) {
    System.out.println( new A_Dash().getB().getDashness());
  }
}
$javac Q2322_1.java
$java -cp . Q2322_1
daaaaaah.

The above is easy to understand, but it is wasteful. From this form, try to use generics. This reduces code and imposes appropriate constraints on the implementer of the extension class, making it more type-safe.

class A_Proto<T extends B> {
  private final T b;

  protected A_Proto( T b) {
    this.b = b;
  }

  public T getB() { return b; }
}

class A extends A_Proto<B> {
  public A() {
    super( new B());
  }
}

class B {}

class A_Dash extends A_Proto<B_Dash> {
  public A_Dash() {
    super( new B_Dash());
  }
}

class B_Dash extends B {
    public String getDashness() { return "daaaaaah."; }
}

public class Q2322_2 {
  public static void main(String argv[]) {
    System.out.println( new A_Dash().getB().getDashness());
  }
}
$javac Q2322_2.java
$java -cp . Q2322_2
daaaaaah.

postscript:

By the way, you can also design without increasing the arguments of the constructor. A_Proto as follows.

abstract class A_Proto<T extends B> {
  private final T b;
  protected A_Proto() {
    this.b = newB();
  }
  protected abstract T newB();
  public final T getB() { return b; };
}

class A extends A_Proto<B> {
  @Override protected B newB() { return new B(); }
}

The implementor of A overrides newB() . It's even simpler because the constructor is removed.

Addendum 2:

And one more thing, I think it's a derailment, but if you want to inherit more classes with abstracted parameters, do the following:

class B {}
class C {}

abstract class A_Proto<T extends B> {
  private final T b;
  public A_Proto() {
    this.b = newB();
  }
  protected abstract T newB();
  public final T getB() { return b; };
}

abstract class Z_Proto<T extends B, T2 extends C> extends A_Proto<T> {
  private final T2 c;
  public Z_Proto() {
    this.c = newC();
  }
  protected abstract T2 newC();
  public final T2 getC() { return c; };
}

Wow. I don't like this. Yes. So you hate Java, right? Yes. The class that inherits this is as follows.

class B2 extends B {}
class C2 extends C {}

class A extends Z_Proto<B2, C2> {
  @Override protected B2 newB() { return new B2(); }
  @Override protected C2 newC() { return new C2(); }
}

Even though the implementation of A is quite easy, the types returned by getB getB() and getC() are B2 and C2 , which makes me feel like I've done a big thing. Sure, the implementation on A was a bit complicated, but both users and implementers of A are comfortable.

There is something I want you to remember from the explanation so far. That is, these examples are "not inheritance for the purpose of inheriting functionality". The A class was defined, but inheritance was used only to " consolidate the type information parameterized by the A_Proto class".

In other words, the design that getB() returns B2 is solidified by the definition of class A There is no way to undo a solid design, and you cannot change the type definition using inheritance.

Call this A class a concrete class for A_Proto . And treat it separately from normal inheritance. Once you've mastered this, you can avoid fatal losses when doing generics and applications.

Scroll to Top