Inheritance and casting: is this good Java?

Take a look at this code ( here )

abstract class EntityA {
    AssocA myA;
    abstract void meet();
}

abstract class AssocA {
    int something;
    abstract void greet();
}

class AssocAConcrete extends AssocA {
    void greet() {
        System.out.println("hello");
    }
    void salute() {
        System.out.println("I am saluting.")
    }
}

class EntityAConcrete extends EntityA {
    void meet() {
        System.out.println("I am about to meet someone");
        ((AssocAConcrete)myA).salute();
    }
}

There are two parallel inheritance trees for the parent class and its associated class. The problem is line 23:

((AssocAConcrete)myA).salute();

This is pain, and I have such things throughout my code. Although this line is part of a specific Entity implementation, I need to be reminded that I want to use a specific AssocA implementation, AssocAConcrete.

Is there any annotation to declare this relationship? Or is there a better, more conversational Java way to express this design? Thank!


This is in response to @Dave because I want to put some code in ...

Interesting! Thus, the call will look something like this:

AssocAConcrete myAssoc = new Assoca();
EnitityA<T extends AssocA> myEntity = new EntityA<AssocAConcrete>();
myEntity.setAssoc(myAssoc);
myAssoc.salute();

Yes? It's really cool. I think I will use it!

+5
4

, , ...

abstract class EntityA<T extends AssocA> {

    // Basically, this means myA is at least an AssocA but possibly more...
    T myA;
    abstract void meet();
}

abstract class AssocA {
    int something;
    abstract void greet();
}

class AssocAConcrete extends AssocA {
    void greet() {
        System.out.println("hello");
    }
    void salute() {
        System.out.println("I am saluting.");
    }
}

class EntityAConcrete extends EntityA<AssocAConcrete> {
    void meet() {
        System.out.println("I am about to meet someone");
        myA.salute();
    }
}

, AssocA. -, (.. , "NotImplementedException" ) . . , (... , , ).

( ):

@pitosalas ...

//Won't work...can't call 'new' on abstract class AssocA
AssocAConcrete myAssoc = new Assoca();

//Instead, do this...
AssocAConcrete myAssoc = new AssocAConcrete();

....

// Again, won't work.  T is only declaring the type inside your class/method.
// When using it to declare a variable, you have to say EXACTLY what you're making,
// or at least something as exact as the methods you're trying to invoke
EnitityA<T extends AssocA> myEntity = new EntityA<AssocAConcrete>();

//Instead do this...
EnitityA<AssocAConcrete> myEntity = new EntityAConcrete();

// Or this...
EntityAConcrete myEntity = new EntityAConcrete();

...

// Assuming this is defined as `public void setAssoc(T newAssoc) {this.myA = newAssoc;}`
myEntity.setAssoc(myAssoc);
myAssoc.salute();
+8

. , , salute AssocA. AssocA ; .

, EntityA AssocA, meet AssocA AssocAConcrete. ; AssocA, AssocAConcrete.

( ) salute greet. , greet, , , . salute . - , runLikeHell.

+3

. , AssocAConcrete EntityAConcrete, .

myA EntityAConcrete AssocAConcrete, . , , , " ", .

0

, "myA", :

public AssocAConcrete myAConcrete = (AssocAConcrete)myA;

Now you can use the new link myAConcreteand access the functions of the class AssocAConcrete.

If you need to do this a lot, as hvgotcodes mentioned, you should definitely consider moving the method to the class AssocA.

0
source

All Articles