Я думаю, что это намного удобнее, если использовать дженерики ...
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();