代码改变世界

学习Objective-C--第二天

2011-06-11 12:39  Paul Wong  阅读(17594)  评论(19编辑  收藏  举报

教程详细:

      技术:Objective-C    难度:初学者     完成时间:20-35分钟

  欢迎来到学习Objective-C系列教程的第二部分,上周 ,我们回顾了Objective-C中的C语言基础,这周呢,我们将会重点介绍到底是什么让Objective-C成为软件开发的优秀语言。特别的,我们还会讨论面向对象编程(OOP)基础,还有怎样用Objective-C去创建一个类和给对象发送消息。

面向对象编程

  为什么还会有Objective-C呢?为什么我们不只用底层的C语言呢?理由是在我们编写程序时Objective-C提供面向对象的能力。OOP是一种编程规范,它让开发者专注于软件设计中的对象和属性,而不是变量和函数。具体的说,OOP试图获取数据抽象,封装,模块化,多态和继承。OOP的主题可以很容易的出一本关于它自己书(或是一个系列教程),所以,我会通过一些例子去介绍这些基本的原则。

  设想一下,你拥有一辆汽车,那你就可以认为这辆汽车是一个对象了。但世界上有许许多多的汽车,并且你也许不止拥有一辆汽车。然而,你的汽车有着种种的属性:牌子呀,类型呀,颜色呀,发动机类型呀等等。在面向对象编程概念里,我们可以把这些概念抽象为汽车“类”,把这个单独的汽车称为这个汽车类的一个对象或者实例(实例化对象)。当一辆汽车被制造时,一个新的汽车类的实例将被实例化(或创建)并且给它设置初始属性。

  说到这里还感觉到模糊吗?还有一个更通俗的例子就是饼模和大饼,类相当于饼模,对象相当于大饼。

  那么,为什么我们还要考虑对象呢?原因之一是:实现生活中,你的大脑很自然地把生活概念化,这样给抽象软件开发带来大大的好处,因为这些是相类似的。

  类(和它的对象)是由方法和属性组成的。如果你是由其他语言过渡过来的,你也许更熟悉等同于方法的函数,等同于属性的变量。好了,这些我们会接着讨论的。

方法

  嗯~,现在我们拥有一个汽车的实例,但我能用它来干什么呢?呵呵,可们可以驾驶它,还可以为它加汽油呀。驾驶和为它加汽油仅仅提供给我们使用的汽车,这就意味着,我们为一辆汽车加油和驾驶它,我们仅仅影响一个实例而已,然而并不是影响到世界所有的汽车哟。因此,为汽车实例加汽油被认为是实例方法,那是我们对我们的实例并且仅仅是我们的实例作影响。

  另一方面,如果我们想问原汽车类汽车可以有多少种颜色供选择,这个时候就是一个类方法了,因为我们不再是涉及到我们自己开的那辆汽车了,而是所有的汽车了。

  许多原则开始变得清晰起来了,好拉,让我们看看一些语法吧。

  在Objective-C中,我们通过发送消息来调用实例方法。当我们想知道我们的汽车实例还有多少汽油时,这时,我们就向实例发送一条消息,这消息就是我们提供的方法。大概看起来是这样的:

1. [recipient message]; 

   方括号表明了我们发送的消息。里面的第一个参数是消息的接收者,第二个参数就是消息了。最后,我们会大部分编程语言一样以分号结束。

   这样下来,对上面的例子已经熟悉了吧。下面是实现如何为我们的汽车实例加汽油的:

1. [dansCar addGas]; 
 
  在上面的例子假设我们实例化了一个名叫“dansCar”的汽车实例。然后,我们向"dansCar”对象发送”addGas”消息,这就赞同于函数调用。在另一种语言里,这行代码可能会像这样:
1. dansCar.addGas();  
 

  属性

   比方说,我们的汽车类有一个用百分比表示汽油存储量的油箱。例如,如果油箱指向50%,那表示它半满的;如果指向100%,那意味着有油箱里装得满满的。现在,如果我们想知道油箱里有多少汽油,我们并不会直接从这个属性里得到信息,相反地,我们通过一个访问方法去访问该属性。同样地,当我们想为汽车加油时,我们并不会给油箱的油量赋上一个新的百分比值,而是使用一个setter来更新属性。这个过程呢,就被称作为数据封装了。

   我们所说的数据封装,其实就是数据的访问要通过访问方法。可能我们当中一些使用其他语言的童鞋们就会为这感到奇怪了,为什么要这样做呢。答案就是,数据封装给类的创建者和类的使用者之间创建了一个很好的缓冲。因为类里的属性是通过类方法去管理和维护的,这样就可以更容易的保证数据的完整性了。还有另外一个主要的好处,当开发者专注于他的类,使用者就不必关心类的内部结构如何。这样,开发者也许升级一个方法,让它变得更快更有效率,然而,这些改动对类的使用者是透明的,他们可以仍然以同样的方法去使用它,不用作代码的改动。

   很好~,我们将接着看看Objective-C是如何把接口和实现分离的。

接口和实现

   当你用Objective-C创建或操作一个简单的类,默认下,你会看到两个文件:一个是实现文件(以.m为后缀名),另一个是接口文件(以.h为后缀名)。

  接口

1. #import <COCOA Cocoa.h>   
2.  
3. @interface Car : NSObject {   
4.  
5.    //This is where attributes go   
6.     float fillLevel;   
7.  
8. }   
9.  
10. //This is where methods go   
11. - (void)addGas;    
12.  
13.@end  

  首先呢,我们引入提供大量可重用代码的Cocoa.h库,里面的代码都可以供我们在编写应用程序时使用。

  下一步,我们声明汽车接口,同时也把NSObject加入声明行里。对"NSObject”的添加意味着汽车类继承于NSObject类。关于继承,我们后续教程会更多的讨论。

  接着,声明实例变量"fillLevel”,为了更容易表现百分比,我们特意指定它为"float”类型。

  下一行,声明"addGas”方法,“”表示这是一个实例方法,而不是类方法。“(void)”部分意味着方法执行结束时不返回任何东西。如果方法要返回一个整型,把这部分替换为”(int)”,其他类型依此类推。最后,我们以分号结束方法的声明。

实现

1. #import "Car.h"    
2.  
3. @implementation Car   
4.  
5. -(void) addGas {   
6.     // code goes here to add gas   
7. }   
8.  
9. @end 

  好了,我们将要模拟为油箱加汽油的场景。同样,我们引入接口文件Car.h。在addGas方法的地方,我们还可以增加更多的方法,但,今天仅仅局限于让大家更好地理解类的工作,而不是如何去完善一个类。

下一节

下一次呢,我们将会深入介绍方法和通过方法使用变量(还有Objective-c的变量管理基础)。这教程不会很长,因为往往开发新手会有一点点理解困难,例如,为什么我们把众多的类划分到多个文件里。如果你也感到有点模糊,那么请重看上面内容或是留言提问。系列教程在不断的由浅入深,理解透这些工作原理是很重要滴。

挑战

  呵呵,本系列的这部分是有点小理论了,没有太多东西可以实践。无论怎样,我建议你今周在苹果开发者网站 注册个帐号,因为这网站会给你更多的参考。当你注册了,你下载一些供下载的简单的类,还有一些小软件。你不必了解所有的代码,你只需要看看如何组织类,如何把类划分到多文件里就可以了。

 

系列教程导航

<<学习Objective-C--第一天                         学习Objective-C--第三天>>