Inherited field in derived class - both solutions look like a llama

I have a class X

with a field A

in it. This is the final field, initialized in the constructor. Now I have a derived class Y

where this field must always be an instance of the B

class derived from A

. The problem is, the class Y

requires a call numerical methods, which are only available for the class B, but not for his ancestor A

.

I see several solutions:

  • Reusing a field of a type A

    inherited from X

    and within a class Y

    casts A

    in B

    . This makes my code full of nasty types.
  • Add another type field B

    . Now there are no reception types, but we have two fields of a slightly different type that must always have the same value - also not very good.
  • Add all the methods that throw B

    also provides . This adds some weird methods that deliberately don't make sense in this class.A

    NotImplementedException

What's the most correct way to deal with this field? Or maybe some other, better exists? I don't think this is very language specific, but should be done in the Java I am using.

+3


source to share


3 answers


Type X should probably be a generic type:



public class X<T extends A> {

    protected T a;

    public X(T a) {
        this.a = a;
    }
}

public clas Y extends X<B> {

    public Y(B b) {
        super(b);
    }

    public void foo() {
        // here, this.a is of type B, without any type cast.
    }
}

      

+5


source


The only sensible solution I can think of is option # 1: add Y

a getter method to the class that returns a non-type field B

, and only access the field through that getter. This will only require one actor, and as a useful side effect, it will also document which parts of the code require the field to actually be B

.



+2


source


Solution # 1 is, in my opinion, the most correct way. If you know that an object belongs to a specific class, there is nothing wrong with giving it to that class. It would be wrong if you were making assumptions about this, but that is not an assumption according to what you say. Maybe make a getter method that just casts the underlying field to the correct type and can be done with it? This way you will only need to do it once (for each subclass).

Solution # 2 will cause subtle runtime errors if the fields somehow stop being properly updated with each other. This seriously sounds like the worst decision.

Solution # 3 still seems like bad software design. If a method exists and it is not in an abstract class and you are not in the prototyping phase, then that method must be implemented. Otherwise, you are probably just setting unnecessary traps for the user (class) by providing a misleading interface to it.

+2


source







All Articles