设计形式之替换原则 — 从二叉树说起
之前我们老师说过,二叉树不是树的特殊情况(意思是指,二叉树不应该作为树的子类) ,当时下面的大部分同学包括我在内都表示无法接受。今天才发现,老师是对的。这是从【替换原则】方面来考虑。
为了说明这个问题,我们来引入另一个数学中常常提到的问题:正方形是一个特殊的矩形。我想这句话在数学方面无人反对,并且也无需反对。但是在面向对象角度来看这样表达很不清楚。我们先来看看替换原则的概念:
┌────────────────────────────────────────────┐
● 如果在任何情况下,子类或实现类都是可以作为基类的替代品。
└────────────────────────────────────────────┘
百度百科:(http://baike.baidu.com/view/1688346.htm)
但是,如果矩形有个调整边长的操作Resize(int widht, int height)。作为矩形,当然可以接受任意比例的数据例如 ( 16, 9 ),那么在我们的某个方法中,你可能会这样写:
void someMethod (Rect & theRect) { //someoperation… theRect.Resize(16, 9 ); //anotheroperatton… }
但是如果传进来的是一个正方形,那么可能会导致异常,而从上面代码来看,完全看不出任何问题:对于矩形来说,( 16, 9 ) 是合法的数据。。。并且,整个过程编译器 0 error(s) and 0 warning(s)。。。
说道这里大家应该知道问题所在了吧?数学上所谓的“特殊情况”,只是指它们具有相同的【属性】,但是数学是忽略【操作】的,而编程的话两者不可缺。那么我们再回头看树的问题,举个简单例子,对于一棵树,它可以随时在任何地方长芽(子树),但是如果你用一棵二叉树去代替,那么…等着加班调试吧^_^。
设计原则:
┌────────────────────────────────────────────┐
● 在使用继承的过程中,子类不能添加任何父类没有的附加约束。
└────────────────────────────────────────────┘
这里问题就很明显了,之所以上面的代码看似正常却容易不明不白抛异常,就是因为违反这一设计原则:
正方形多了个矩形没有的限制:长必须等于宽。
二叉树多了个树没有的限制:子树不能超过两棵
文章到这里,有不同意见欢迎留言讨论O(∩_∩)O~