Java继承场景下如何让Getter方法返回子类对应的属性类型
问题说明
现有继承结构中,父类MyClass定义的getMyAttribute()方法返回值固定为MyAttribute类型,即使子类MySubClass实际持有的属性是MySubAttribute实例,调用该方法的返回值也会被向上转型为父类类型,无法直接识别为MySubAttribute类型。
可选实现方案
- 方案1:利用Java协变返回类型特性,子类重写getter方法
Java 5及以上版本支持子类重写方法时,返回值类型为父类方法返回值类型的子类(即协变返回)。不需要修改父类代码,仅需在MySubClass中重写get方法即可:
class MySubClass extends MyClass { MySubClass(MySubAttribute mySubAttribute) { super(mySubAttribute); } @Override MySubAttribute getMyAttribute() { // 构造方法已约束传入参数必为MySubAttribute,强转安全 return (MySubAttribute) super.getMyAttribute(); } }
改造后调用mySubClass.getMyAttribute()时,返回值静态类型即为MySubAttribute,可直接调用子类独有的doSomethingElse()方法,无需外部手动强转。
- 方案2:泛型改造父类,从编译期约束类型
如果存在多个MyClass子类对应不同MyAttribute子类的扩展场景,可将父类定义为泛型类,从类型定义层面绑定属性类型:
// 泛型参数限定为MyAttribute或其子类 class MyClass<T extends MyAttribute> { T myAttribute; MyClass(T myAttribute) { this.myAttribute = myAttribute; } T getMyAttribute() { return myAttribute; } } // 子类指定泛型实参为MySubAttribute class MySubClass extends MyClass<MySubAttribute> { MySubClass(MySubAttribute mySubAttribute) { super(mySubAttribute); } }
该方案不需要在子类中编写强转逻辑,类型安全由编译器校验,后续新增其他子类时只需指定对应泛型参数即可,可维护性更强。
注意:不要在外部调用时手动强转返回值,这种写法会把类型转换逻辑散落在业务代码中,容易引发类型转换异常,上述两种方案都可以把类型收敛在类定义内部。
内容的提问来源于stack exchange,提问作者emerick biron
相关产品推荐
相关产品推荐

