组合和继承,是拿到一个问题,设计相应的Java类的时候,不得不面对的来自灵魂的拷问。
“XX到底是YY的一种,还是只是组合了YY?”,”手机到底是手电筒的一种,还是组合了一个可以当手电的闪光灯?”
is-a与has-a关系
is-a( 是 “a” 小明是人类)表示的是属于得关系。比如兔子属于一种动物(继承关系)。
has-a( 有 “a” 汽车有轮胎) 表示组合,包含关系。比如兔子包含有腿,头等组件;就不能说兔子腿是属于一种兔子(不能说是继承关系)
继承与组合的区别
继承,其实表达的是一种”is-a”的关系,也就是说,在你用类构造的世界中,”子类是父类的一种特殊类别”。
组合,在类中创建另一个类的对象,来进行各种操作。
继承不是组合,继承也不只是为了能简单的拿来父类的属性和方法。如果仅仅如此,原封不动的拿来主义,组合也能做到。
继承也不是通过组合的方式来实现的。和组合相比,继承更像是”融合”。
所谓融合,即合二为一,可以互相影响。父类影响子类没问题,子类怎么影响父类呢?如何限制手机一次只能最多买五个?
我们为什么需要使用继承?
如果使用组合,对于作为属性的类对象,我们无法修改其方法。有时候是因为没有权限,有时候是因为我们的习惯:我们不该为了一个类去修改作为其属性的另一个类的方法。对于组合这种方式,我们只有使用的权限,而没有修改的权限。也就是说组合很难做到上面提到的限制手机买5个。
而对于继承,因为有覆写的存在,因此,虽然某个方法属于父类,但如果子类想要拥有区别于父类的属于自己的独特的方法,那么可以使用覆写机制。所以,对于继承这种方式,我们不仅可以使用,还可以修改。
继承之于组合特殊的一点在于,它能够进行覆写,对继承自父类的方法不满足就可以修改。而在Java中,组合是没有覆盖的,覆盖只在继承中存在。
即组合,我们从其他类简单地拿来了属性和方法;而继承,我们不仅仅从其他类拿来了属性和方法,我们还可以修改拿来的方法。
组合让两个类相对保持自己的独立性,而继承则让两个类相互渗透,因为继承更确切地说是子类和父类的融合。
类存在的目的是封装,而继承在某种程度上破坏了这种封装,让两个类紧紧耦合在了一起。
覆盖(重写)的实例
1 | package test; |