封装、继承、多态是OO的三大特性,由此可见继承思想的重要性。但是,不少人对继承的理解过多地局限在OOP层面,从而限制了继承思想在OOD层面的巨大作用。笔者认为,软件工程师应该不断提升对OO思想的认识层面,加强实际开发能力。
本文站在OOD的角度,将继承看成实现OOD的强大手段,通过具体例子,说明针对接口编程(Program To An Interface)、混入类(Mix In Class)、基于角色的设计(Role-based Design)这三个与继承紧密相关的著名OOD技巧。
一、从一则禅师语录说起
《五灯会元》卷十七中,有一则青原惟信禅师的语录:“老僧三十年前未参禅时,见山是山,见水是水。及至后来亲见知识,有个入处,见山不是山,见水不是水。而今得个休歇处,依前见山只是山,见水只是水。”
禅师高论,颇具哲理,讲的是悟道的过程。其实,领悟OOD之道的过程又何尝不是如此呢?
1、见继承是继承——程序员境界
初学OOP的人,大多处在“见继承是继承”的层面,最关心的是类的语法、类的成员变量、类的成员函数等这些实现层的东西。这是程序员境界。
2、见继承不是继承——成长境界
开始研习OOD之时,又往往跳到另一个极端,只关心设计,而无心(也可能是无力)关心实现,处在所谓“见继承不是继承”的层面。在这个阶段的人,脑中的兴奋点是“设计”,是职责分配、接口设计、可重用性、可扩展性、耦合度、聚合度等这些设计层的概念。这是成长境界。
3、见继承只是继承——设计师境界
学通OOD之后,会达到“见继承只是继承”的层面。一个“只”字,体现了继承背后的“设计理念”才是该境界的要害。但是,这个阶段和第二阶段不同,第二阶段是一味的否定,而本阶段是否定之否定,把OOP层面的继承机制看成用来实现特定OOD的手段加以利用。这是设计师境界。
二、从OOD层面认识继承
在OOP层面,除了类、成员变量、成员函数这些最基本的概念,最重要的就是代码重用和名字空间的可见性了。而OOD层面,最基本的概念是类、职责、状态、角色这些更抽象一级的概念,及其相关的耦合度、聚合度、可重用性、可扩展性、可维护性等。可见,虽然OOD最终要依赖OOP作为实现手段,但显然OOD和OOP并非在同一抽象级上,有不同的概念体系和思维方式。
再说继承。单纯从OOP层面看,继承是一个通过复用父类功能而扩展应用功能的基本机制,它允许你根据旧的类快速定义新的类;还有些人用继承仅为了获取名字空间的可访问性。但是,从OOD层面看,继承可以演变出 “Is-A”、“Plays Role Of”等抽象的设计概念。因此,担任设计师角色的人如果自己还限制在OOP的层面,“设计乏术”的局面是不可避免的。总之,提升对继承的认识,对活用接口继承和实现继承这两种继承机制来实现OOD意图非常重要。
与继承相关的OOD技巧有很多,本文仅讨论比针对接口编程、混入类、基于角色的设计这三种技巧,下图展示了它们和继承的关系。
本文站在OOD的角度,将继承看成实现OOD的强大手段,通过具体例子,说明针对接口编程(Program To An Interface)、混入类(Mix In Class)、基于角色的设计(Role-based Design)这三个与继承紧密相关的著名OOD技巧。
一、从一则禅师语录说起
《五灯会元》卷十七中,有一则青原惟信禅师的语录:“老僧三十年前未参禅时,见山是山,见水是水。及至后来亲见知识,有个入处,见山不是山,见水不是水。而今得个休歇处,依前见山只是山,见水只是水。”
禅师高论,颇具哲理,讲的是悟道的过程。其实,领悟OOD之道的过程又何尝不是如此呢?
1、见继承是继承——程序员境界
初学OOP的人,大多处在“见继承是继承”的层面,最关心的是类的语法、类的成员变量、类的成员函数等这些实现层的东西。这是程序员境界。
2、见继承不是继承——成长境界
开始研习OOD之时,又往往跳到另一个极端,只关心设计,而无心(也可能是无力)关心实现,处在所谓“见继承不是继承”的层面。在这个阶段的人,脑中的兴奋点是“设计”,是职责分配、接口设计、可重用性、可扩展性、耦合度、聚合度等这些设计层的概念。这是成长境界。
3、见继承只是继承——设计师境界
学通OOD之后,会达到“见继承只是继承”的层面。一个“只”字,体现了继承背后的“设计理念”才是该境界的要害。但是,这个阶段和第二阶段不同,第二阶段是一味的否定,而本阶段是否定之否定,把OOP层面的继承机制看成用来实现特定OOD的手段加以利用。这是设计师境界。
二、从OOD层面认识继承
在OOP层面,除了类、成员变量、成员函数这些最基本的概念,最重要的就是代码重用和名字空间的可见性了。而OOD层面,最基本的概念是类、职责、状态、角色这些更抽象一级的概念,及其相关的耦合度、聚合度、可重用性、可扩展性、可维护性等。可见,虽然OOD最终要依赖OOP作为实现手段,但显然OOD和OOP并非在同一抽象级上,有不同的概念体系和思维方式。
再说继承。单纯从OOP层面看,继承是一个通过复用父类功能而扩展应用功能的基本机制,它允许你根据旧的类快速定义新的类;还有些人用继承仅为了获取名字空间的可访问性。但是,从OOD层面看,继承可以演变出 “Is-A”、“Plays Role Of”等抽象的设计概念。因此,担任设计师角色的人如果自己还限制在OOP的层面,“设计乏术”的局面是不可避免的。总之,提升对继承的认识,对活用接口继承和实现继承这两种继承机制来实现OOD意图非常重要。
与继承相关的OOD技巧有很多,本文仅讨论比针对接口编程、混入类、基于角色的设计这三种技巧,下图展示了它们和继承的关系。