类的复用基本是三种方式,组合,代理,继承。为了同样的复用目的,都是想在构建一个新类的时候加入一个已有类的对象。使用组合是直接在一个新类中new一个对象,使用继承其实也是通过构造方法中调用父类构造方法隐式的加入一个已有类的对象,所不同的是,使用组合更具灵活性,可以自主的选择需要加入什么对象,而使用继承则是强迫必须加入一个父类的对象。另外还可以使用代理,通过在新类中创建一个对象,并在方法中调用这个对象的方法,从而达到包装一个新方法的目的。尽管面向对象编程对继承极力强的,但在设计一个新类的时候,一般应有效选择组合(或者可能是代理),确实必要的时候才使用继承。实际上应该很少去继承一具体的类,大多数时候应该考虑继承抽象类和去实现接口。
创建一新类到底应该使用组合还是继承,判断的标准应该是新类是否需要向上转型,也就是说新类是否需要复用接口。
思考一个问题的时候,目的是很重要的,必须不断问自己的目的是什么。同样为的是复用类,采用不同的方法会有不同的效果。但是首要考虑的应该是降低类的复杂度,这也是OOP思想的出发点。尽量简化问题。
一 关于组合
在类中初始化对象的位置
1.在定义对象的地方,这意味着总是能够在构造器调用之前被初始化
2.在类的构造器中
3.就在使用这些对象之前进行初始化,这样的初始化叫做惰性初始化,在生成对象不值得及不必每次都生成对象的情况下,这样做明显会减少很多负担
4.使用实例初始化,比如在声明一个String对象的同时初始化她:String s ="实例初始化";
二 关于继承
继承一个类是通过在新类的构造方法中强迫去调用父类的构造方法来实现的。这样做更本质的讲相当于每次在new一个新类的对象时都必须先new一个父类的对象。简单说,当创建一个导出类对象时,该对象包含了一个基类的对象。
为了继承,一般的规则是将类的所有成员变量都指定为private,将所有的方法都指定为public.这样做能够保证顺利继承,以后再去完善是否需要设置protected或者把一个方法设置为private.另外可以在导出类中使用"super.方法名"来强调调用的是父类的方法,这样做可以在想复写基类方法的时候需要去调用基类这个同名方法的时候得到好处。
明显,使用继承的好处是可以向上转型。实质是子类继承了父类的接口,由于这些被强迫继承的接口是一样的,所以可以把子类对象向上转型为父类(即让一个父类的引用变量指向一个子类对象),从而通过父类的视野去使用。简单的说,子类向上转型后仅能看见父类的成员,也就是说不能访问子类新增的成员,但是调用一个方法的时候,编译器会去做动态绑定以保证能够调用到被改写的方法。
所以说单纯继承是一种“纯替代”是一种is-a的关系,扩展继承是一种“like-a”的关系。
三 关于代理
当想复用一个类的部分方法时,在新类中创建一个成员对象后,在新类中的方法中通过这个成员对象去调用它自己的方法,这种包装成员方法来获得一个新方法的技术可以避免继承导致完全暴露父类方法的问题。这是一种十分灵活的技术。可以趣称为“部分继承”。
代理——灵活的包装方式。