类的成员初始化变量, 其实有若干种.
1. 直接赋值
class A{
Object b=new B();
}
然而, 有时候我们不想让该类进行赋值, 想将赋值权力交给子类, 通常我们的想法是让子类覆盖该成员变量 , 如下(Java 成员变量不存在多态)
public SubA extned A{
super.b=new B();// 无法这样使用
}
只能如下
public subA extend A{
//可以这样做
public subA(){
super.b=new B();
}
}
优点:
- 简洁
缺点 :
- 不利于成员变量的读取与写入。
- 若存在相同名称的变量,容易搅混
- 赋值操作需要触发
参考:
why instance variable of super class is not overridden in sub class method
针对上述情况, 使用抽象方法显得有优势
- ##### 抽象类
abstratc class AbstractA{
public abstratc B getB();
}
class SubA extend AbstractA{
//实现父类的虚拟方法
public B getB{
return new B;
}
}
//等价于
class SubA extend AbstractA{
final B b=new B();
public B getB{
return b;
}
}
解决了(2)(3)问题,(1)问题中写入并没有解决。
另外存在 【无状态】的缺点
改良 (使之具有状态)
//(1)种 具有默认值
class SubA extend AbstractA{
private B b=new B();
//实现父类的虚拟方法
public B getB{
return b;
}
}
//(2)种 状态插入移交外部
class SubA extend AbstractA{
private B b;
public void setB{
this.b=b;
}
//实现父类的虚拟方法
public B getB{
return b;
}
public static void main(...){
SubA a=new SubA();
a.setB(new B());
}
}
解决上述问题。
缺点
- 状态等操作仍需手工加入
成员变量过多
(资源类)使用bean方式存储, 并让该参数bean进行赋值
(可以分离成资源类,通过set资源类进行链接。 )
class Resource {//Bean或者资源类
B b;
}
class AbstractA{
public void setResource(Resource re);
}
public class A extends AbstractA{
B b;
//插入并分解资源
@override
public void setResource(Resource re){
b=re.b;
}
}
其他解决方案
使用文字或者demo 进行提示子类该如何实现
-
使用接口代替虚拟函数
初始化位置
使用set方式触发初始化 ,初始化位置有如下
- 平台
- 构造函数 , 成员变量 等
- 每个执行方法的第一行
public abstrac class abstracA{
A a;
public methodA(){
a=initA();
}
abstract A initA();
}