我们知道java语言有三大特性:封装,继承,多态
但是继承和封装却是一对有点矛盾的两个方面,怎么理解??
我们想想:封装的目的是想让隐藏类中的属性和方法。但是在继承过程中,我们的子类肯定会继承父类的方法和字段,而且我们还可以覆盖父类的方法
着就有一点破坏封装 要隐藏类属性的目的了!虽然我们可以同过声明变量和方法是private来避免类的属性和方法被继承,
但是如果属性和方法都使用private不让子类继承,那么三大特性之一继承不就是没有意义了吗???
我们还是看看继承在java中时怎么实现的
public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Bird bird=new Bird(); bird.beat(); bird.breath(); bird.fly(); Wolf wolf=new Wolf(); wolf.beat(); wolf.breath(); wolf.run(); } } //Bird和Wolf类的父类 class Animal { public void beat() { System.out.println("心脏跳动"); } public void breath() { System.out.println("努力呼吸"); } } //继承自Animal类 class Bird extends Animal { public void fly() { System.out.println("鸟儿飞啊飞"); } public void beat() { System.out.println("bird is beating"); } } //继承自Animal类 class Wolf extends Animal { public void run() { System.out.println("跑啊跑"); } //子类覆盖了父类的方法 public void breath() { System.out.println("wolf is breathing"); } }
在上面的继承例子中,我们看到了父类的方法被子类覆盖,这种继承对类的封装是不利的!
为了提高类的封装,我们提出组合,组合是通过将原先的父类的方法和属性跟子类重新组合成一个新的类型!
class Animal { public void beat() { System.out.println("心脏跳动"); } public void breath() { System.out.println("努力呼吸"); } } class Bird { private Animal animal; public Bird(Animal animal) { this.animal=animal; } private void fly() { System.out.println("鸟儿飞啊飞"); } public void beat() { //将“父类”的方法直接组合进来 animal.beat(); } } class Wolf { private Animal animal; public Wolf(Animal animal) { this.animal=animal; } public void run() { System.out.println("跑啊跑"); } //将“父类”的方法直接组合进来 public void breath() { animal.breath(); } }
复用其实就是在新的类型中声明要复用的类的对象,并将要复用类方法的嵌入到新类相同的方法中
我们可以看出:在java我们为了复用某个类中的成员,我们可以用继承的方法,但是为了不破坏类封装的特性,我们还可以用组合的方法,来实现复用!
我们可以想想复用和继承的优缺点:
1.复用让类更封装,但是真大了编程量,因为每个父类的方法都得手动嵌入如:beath()
2.复用和封装消耗的内存空间差不多,他们都得为方法好字段分配存储位置!