潜鱼在渊

Concentrating on Architectures.

posts - 77, comments - 309, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

代码检查(3)

Posted on 2008-10-26 01:42 非鱼 阅读(2514) 评论(1)  编辑  收藏 所属分类: 面向对象设计Java技术
3. 父类引用子类

这是说一个父类保存了其子类的引用,返回具体的其子类类型,以具体的其子类类型做为方法的参数,或者在方法中以本地变量的方式使用、初始化了具体的其子类实例。一句话,父类的任何地方都不应该出现“以其子类型”定义的静态变量、实例变量和本地变量(Local variables)。

组合关系

父类组合(Composite)其子类的关系不能存在,因为这会导致运行时刻的递归初始化,产生StackOverflow错误,代码如下:

public class Base {
  Derived d = new Derived();

  // 或者在构造方法中调用new Derived();
  public Base() {
    d = new Derived();
  }
}

public class Derived extends Base {
}

只要存在父类组合其子类的关系,即要在父类初始化时刻同时初始化其子类,必定导致这样的问题,无论是在定义实例变量的时候初始化,还是在构造器中初始化。当然,即使实例变量定义为父类,如果实际初始化的是其子类,也会产生同样的错误。

聚合关系

父类聚合(Aggregate)其子类的关系也不应该存在。聚合关系和组合关系的不同就在于初始化过程,在聚合关系中,其子类的初始化不在父类初始化过程中,这不会导致递归问题。但这并不是说这样做就是好的。

直接以其子类型定义静态变量、实例变量,等于把抽象的父类绑定到了具体的子类型。这是对“继承关系是一种抽象关系”的破坏,它使更抽象的父类不再具有抽象的涵义。

在父类方法的实现中,以其子类型定义本地变量,和父类聚合其子类“效果”是一样的。

以父类型或者更抽象的类型来定义变量

在父类中,可以使用父类型或者更抽象的类型来定义变量。虽然不是一种很好的实践,但有时的确需要把其子类型的实例付值给这些变量。一般情况下,这样做的时候会选择动态加载子类的实例:

public abstract class Factory {
  private static Factory instance;

  public synchronized static Factory getInstance() {
    // 从配置文件中读取子类型名称
    String factoryName = readFromConfig();
    instance = Class.forName(factoryName).newInstance();
    ....
  }

  public Object createSomething();
}

即使如此,我个人的看法是,尽可能避免使用子类的实例。


, , , ,


评论

# re: 代码检查(3)  回复  更多评论   

2008-12-22 16:04 by lbom
先有父,才有子,按楼主的写法,是在父类中使用子类,是不是有点顺序颠倒哦。
通常的用法可以使用虚拟父类+子类来构建父子关系

只有注册用户登录后才能发表评论。


网站导航: