到目前为止,对象是对问题进行抽象的单位和程序中互相作用的角色。当然,这一切都需要编程语言的支持。其中最重要的两个机制是:封装和多态。
封装保证了类的实现和接口分离,多态赋予了每个类自己的名字空间。下面的章节将对这两种机制进行具体介绍。
本节包括如下内容:
封装
多态
封装
为了保证在对问题的抽象中能够进行有效的设计,您必须从通用的接口考虑问题而不用考虑这些接口的实现细节。对于实际程序中的对象来说,实现和接口之间的分离必须有语言机制的保证。接口必须能够封装实现——也就是对于程序的其他部分是隐藏的。封装能够防止无意中访问了对象的实现细节。
在C语言中,函数就是封装的一个很好的例子。函数的实现对于程序的其他部分以及函数体外的任何代码来说都是不可访问的。对象的方法和实例变量也是类似的封装,在对象内可见,对象外不可见。实例变量的封装有时候也被称作信息隐藏。
初看起来,把实例变量中信息隐藏起来似乎限制了您作为一个程序员的自由。实际上,它给予了您更大的空间和更大的自由。如果对象的实现能够对外可见,对象的实现者和对象的用户就不得不产生联系。他们作任何改动时就不得不考虑到对方的实现。
例如,假设您对用水模型程序中的水龙头对象比较感兴趣,并考虑在您写的程序中使用该对象。如果该对象的接口是确定的,您就无须关心该对象的其他事情,如bug的修正,更好的优化等。您不用对您的程序作任何改动就会自动的得到这些好处,因为您仅仅依赖于该对象的接口,和该对象的实现是分离的。
此外,尽管水龙头对象的实现者可能会对您如何使用该对象感兴趣,并且试图满足您的需要,但是只要该对象的接口是确定的,他就无须关心您怎样在代码中使用该对象。您也无法限制对象的实现,因为对象的实现和对象的使用者是分离的。
多态
不同对象以自己的方式响应相同的消息的能力叫做多态。
由于每个类都属于该类的名字空间,这使得多态称为可能。类定义中的名字和类定义外的名字并不会冲突。类的实例变量和类方法有如下特点:
和C语言中结构体中的数据成员一样,类的实例变量也位于该类独有的名字空间。
类方法也同样位于该类独有的名字空间。与C语言中的方法名不同,类的方法名并不是一个全局符号。一个类中的方法名不会和其他类中同样的方法名冲突。两个完全不同的类可以实现同一个方法。
方法名是对象接口的一部分。对象收到的消息的名字就是调用的方法的名字。因为不同的对象可以有同名的方法,所以对象必须能理解消息的含义。同样的消息发给不同的对象,导致的操作并不相同。
多态的主要好处就是简化了编程接口。它容许在类和类之间重用一些习惯性的命名,而不用为每一个新加的函数命名一个新名字。这样,编程接口就是一些抽象的行为的集合,从而和实现接口的类的区分开来。
重载: 多态和参数重载通常描述的是同一件事情,但是角度有轻微的不同。多态是从多元化的角度,不同的类可以有同名方法。参数重载则是从方法名的角度,随着参数的不同,方法会有不同的效果。操作符重载也是类似的情况。操作符重载是指将语言的操作符(例如 C语言中的==和+)用方法来描述的能力,并且随参数类型的不同操作符具有不同的含义。Objective-C支持方法名的多态,但不支持参数和操作符的多态。
例如,假设您需要知道一段时间内各种装置对象用水量。您不用给装置类定义一个amountConsumed方法,给水龙头类定义一个amountDispensedAtFaucet方法,给建筑类定义一个cumulativeUsage方法,而是简单的给每个类都定义一个waterUsed方法。这大大减少了那些概念上是同一个操作的方法的数量。
多态也使得代码可以分散在不同的对象中而不用试图在一个函数中考虑到所有可能的对象。这样使得您的代码扩展性和复用性更好一些。当一个新的情景出现时,您无须对现有的代码进行改动,而只需要增加一个新的类和新的同名方法。
例如,假设您的代码发送了一个 draw消息给一个对象。随着接收对象的不同,这个消息可能会产生两种不同的图像。当您需要增加第三种图像时,您仅仅需要将这个消息发给另外一个对象,而不用对消息本身或者现有对象的代码作任何改动。
封装保证了类的实现和接口分离,多态赋予了每个类自己的名字空间。下面的章节将对这两种机制进行具体介绍。
本节包括如下内容:
封装
多态
封装
为了保证在对问题的抽象中能够进行有效的设计,您必须从通用的接口考虑问题而不用考虑这些接口的实现细节。对于实际程序中的对象来说,实现和接口之间的分离必须有语言机制的保证。接口必须能够封装实现——也就是对于程序的其他部分是隐藏的。封装能够防止无意中访问了对象的实现细节。
在C语言中,函数就是封装的一个很好的例子。函数的实现对于程序的其他部分以及函数体外的任何代码来说都是不可访问的。对象的方法和实例变量也是类似的封装,在对象内可见,对象外不可见。实例变量的封装有时候也被称作信息隐藏。
初看起来,把实例变量中信息隐藏起来似乎限制了您作为一个程序员的自由。实际上,它给予了您更大的空间和更大的自由。如果对象的实现能够对外可见,对象的实现者和对象的用户就不得不产生联系。他们作任何改动时就不得不考虑到对方的实现。
例如,假设您对用水模型程序中的水龙头对象比较感兴趣,并考虑在您写的程序中使用该对象。如果该对象的接口是确定的,您就无须关心该对象的其他事情,如bug的修正,更好的优化等。您不用对您的程序作任何改动就会自动的得到这些好处,因为您仅仅依赖于该对象的接口,和该对象的实现是分离的。
此外,尽管水龙头对象的实现者可能会对您如何使用该对象感兴趣,并且试图满足您的需要,但是只要该对象的接口是确定的,他就无须关心您怎样在代码中使用该对象。您也无法限制对象的实现,因为对象的实现和对象的使用者是分离的。
多态
不同对象以自己的方式响应相同的消息的能力叫做多态。
由于每个类都属于该类的名字空间,这使得多态称为可能。类定义中的名字和类定义外的名字并不会冲突。类的实例变量和类方法有如下特点:
和C语言中结构体中的数据成员一样,类的实例变量也位于该类独有的名字空间。
类方法也同样位于该类独有的名字空间。与C语言中的方法名不同,类的方法名并不是一个全局符号。一个类中的方法名不会和其他类中同样的方法名冲突。两个完全不同的类可以实现同一个方法。
方法名是对象接口的一部分。对象收到的消息的名字就是调用的方法的名字。因为不同的对象可以有同名的方法,所以对象必须能理解消息的含义。同样的消息发给不同的对象,导致的操作并不相同。
多态的主要好处就是简化了编程接口。它容许在类和类之间重用一些习惯性的命名,而不用为每一个新加的函数命名一个新名字。这样,编程接口就是一些抽象的行为的集合,从而和实现接口的类的区分开来。
重载: 多态和参数重载通常描述的是同一件事情,但是角度有轻微的不同。多态是从多元化的角度,不同的类可以有同名方法。参数重载则是从方法名的角度,随着参数的不同,方法会有不同的效果。操作符重载也是类似的情况。操作符重载是指将语言的操作符(例如 C语言中的==和+)用方法来描述的能力,并且随参数类型的不同操作符具有不同的含义。Objective-C支持方法名的多态,但不支持参数和操作符的多态。
例如,假设您需要知道一段时间内各种装置对象用水量。您不用给装置类定义一个amountConsumed方法,给水龙头类定义一个amountDispensedAtFaucet方法,给建筑类定义一个cumulativeUsage方法,而是简单的给每个类都定义一个waterUsed方法。这大大减少了那些概念上是同一个操作的方法的数量。
多态也使得代码可以分散在不同的对象中而不用试图在一个函数中考虑到所有可能的对象。这样使得您的代码扩展性和复用性更好一些。当一个新的情景出现时,您无须对现有的代码进行改动,而只需要增加一个新的类和新的同名方法。
例如,假设您的代码发送了一个 draw消息给一个对象。随着接收对象的不同,这个消息可能会产生两种不同的图像。当您需要增加第三种图像时,您仅仅需要将这个消息发给另外一个对象,而不用对消息本身或者现有对象的代码作任何改动。