从C++ 到Objective-C(1):前言
作者: DevBean 日期: 2011 年03 月18 日发表评论 (6)查看评论
Objective-C 可以算作Apple 平台上“唯一的”开发语言。很多Objective-C 的教程往往直接从Objective-C 开始讲起。不过,在我看来,这样做有时候是不合适的。很多程序员往往已经掌握了另外一种开发语言,如果对一门新语言的理解建立在他们已有的知识之上,更能起到事半功倍的效果。既然名为Objective-C,它与 C 语言的联系更加密切,然而它又是Objective 的。与 C 语言联系密切,并且是Objective 的,我们能够想到的另外一门语言就是C++。C++ 的开发人员也更普遍,受众也会更多。于是就有了本系列,从C++ 的角度来讲述Objective-C 的相关知识。不过,相比C++,C# 似乎更近一些。不过,我们还是还用C++ 作为对比。这个系列不会作为一个完整的手册,仅仅是入门。本系列文章不会告诉你Objective-C 里面的循环怎么写,而是通过与C++ 的对比来学习Objective-C 一些更为高级的内容,例如类的实现等等。如果要更好的使用Objective-C,你需要阅读更多资料。但是,相信在本系列基础之上,你在阅读其他资料时应该会理解的更加透彻一些。
说明:本系列大致翻译来自《From C++ to Objective-C》,你可以在这里到它的英文pdf 版本。
下面来简单介绍一下Objective-C。
要说Objective-C,首先要从Smalltalk 说起。Smalltalk 是第一个真正意义上的面向对象语言。Smalltalk 出现之后,很多人都希望能在 C 语言的基础之上增加面向对象的特性。于是就出现了两种新语言:C++ 和Objective-C。C++ 不必多说,很多人都比较熟悉。Objective-C 则比较冷门。它完全借鉴了Smalltalk 的思想,有着类似的语法和动态机制;相比来说,C++ 则更加静态一些,目的在于提供能好的性能。Objective-C 最新版本是 2.0.我们的这个系列就是以Objective-C 2.0 为基础讲解。
Objective-C 是一门语言,而Cocoa 是这门语言用于MacOS X 开发的一个类库。它们的关系类似于C++ 和Qt,Java 和Spring 一样。所以,我们完全可以不使用Cocoa,只去用Objective-C。例如gcc 就是一个不使用Cocoa 的编译器。不过在MacOS X 平台,几乎所有的功能都要依赖Cocoa 完成。我们这里只是做一个区别,应该分清Objective-C 和Cocoa 的关系。
从C++ 到Objective-C(2):语法概述
作者: DevBean 日期: 2011 年03 月18 日发表评论 (0)查看评论
关键字
Objective-C 是C 语言的超集。类似于C++,良好的C 源代码能够直接被Objective-C 编译器编译。不同于C++ 直接改变 C 语言的设计思路,Objective-C 仅仅是在 C 语言的基础上增加了一些概念。例
如,对于类的概念,C++ 是增加了一个全新的关键字class,把它作为语言内置的特性,而Objective-C 则是将类转换成一个struct 去处理。所以,为了避免冲突,Objective-C 的关键字都是以@ 开头。一个简单的关键字列表是:@class, @interface, @implementation, @public, @private, @protected, @try, @catch, @throw, @finally, @end, @protocol, @selector, @synchronized,
@encode, @defs。Objective-C 2.0 又增加了@optional, @required, @property, @dynamic, @synthesize 这几个。
另外的一些值同样也类似于关键字,有nil 和Nil, 类型id, SEL 和BOOL, 布尔变量YES 和NO。最后,特定上下文中会有一些关键字,分别是:in, out, inout, bycopy, byref, oneway 和getter, setter, readwrite, readonly, assign, retain, copy, nonatomic 等。
很多继承自NSObject 的函数很容易与关键字混淆。比如alloc, release 和autorelease 等。这些实际都是NSObject 的函数。另外一个需要注意的是self 和super。self 实际上是每一个函数的隐藏参数,而super 是告知编译器使用self 的另外语义。
注释
Objective-C 使用// 和/*…*/ 两种注释风格。
变量声明的位置
Objective-C 允许在代码块的中部声明变量,而不仅仅在块的最开始处。
新增的值和变量
BOOL, YES, NO
C++ 中使用bool 表示布尔类型。Objective-C 中则是使用BOOL,其值为YES 和NO。
nil, Nil 和id
简单来说:
∙每一个对象都是id 类型的。该类型可以作为一种弱类型使用。id 是一个指针,所以在使用时应注意是否需要再加*。例如id *foo = nil,实际是定义一个指针的指针;
∙nil 等价于指向对象的NULL 指针。nil 和NULL 不应该被混用。实际上,nil 并不简单是NULL 指针;
∙Nil 等价于指针nil 的类。在Objective-C 中,一个类也是一个对象(作为元类Meta-Class 的实例)。nil 代表NULL 指针,但它也是一个类的对象,nil 就是Nil 类的实例。C++ 没有对应的概念,不过,如
果你熟悉Java 的话,应该知道每一个类对象都对应一个Class 实例,类似这个。
SEL
SEL 用于存储选择器selector 的值。所谓选择器,就是不属于任何类实例对象的函数标识符。这些值可以由@selector 获取。选择器可以当做函数指针,但实际上它并不是一个真正的指向函数的指针。
@encode
为了更好的互操作性,Objective-C 的数据类型,甚至自定义类型、函数或方法的元类型,都可以使用ASCII 编码。
@encode(aType) 可以返回该类型的C 字符串(char *)的表示。
源文件
与C++ 类似,Objective-C 同样建议将声明和实现区分开。Objective-C 的头文件后缀名是 .h,源代码后缀名是 .m。Objective-C 使用#import 引入其它头文件。与#include 不同的是,#import 保证头文件只被引入一次。另外,#import 不仅仅针对Objective-C 的头文件,即便是标准 C 的头文件,比如stdlib.h,同样可以使用#import 引入。
我们前面看到的类NSObject,NSString 都有一个前缀NS。这是Cocoa 框架的前缀(Cocoa 开发公司是NeXTStep)。
函数和方法的区别
Objective-C 并不是“使用方括号表示函数调用”的语言。一开始很容易把
理解成
但实际上并不是这么简单。Objective-C 是 C 语言的超集,因此,函数和 C 语言的声明、定义、调用是一致的。C 语言并没有方法这一概念,因此方法是使用特殊语法,也就是方括号。不仅仅是语法上的,语义上也是不同的:这并不是方法调用,而是发送一条消息。看上去并没有什么区别,实际上,这是Objective-C 的强大之处。例如,这种语法允许你在运行时动态添加方法。
从C++ 到Objective-C(3):类和对象
作者: DevBean 日期: 2011 年03 月19 日发表评论 (0)查看评论object to
既然是面向对象语言,类和对象显然是应该优先考虑的内容。鉴于本系列已经假定你已经熟悉C++ 语言,自然就不会去解释类和对象的含义。我们直接从Objecti-C 和C++ 的区别开始说起。
Objetive-C 使用的是严格的对象模型,相比之下,C++ 的对象模型则更为松散。例如,在Objective-C 中,所有的类都是对象,并且可以被动态管理:也就是说,你可以在运行时增加新的类,根据类的名字实例化一个类,以及调用类的方
法。这比C++ 的RTTI 更加强大,而后者只不过是为一个“static”的语言增加的一点点功能而已。C++ 的RTTI 在很多情况下是不被推荐使用的,因为它过于依赖编译器的实现,牺牲了跨平台的能力。
根类,id 类型,nil 和Nil 的值
任何一个面向对象的语言都要管理很多类。同Java 类似,Objective-C 有一个根类,所有的类都应该继承自这个根类(值得注意的是,在Java 中,你声明一个类而不去显式指定它继承的父类,那么这个类就是Object 类的直接子类;然而,在Objective-C 中,单根类的子类必须被显式地说明);而C++ 并没有这么一个类。Cocoa 中,这个根类就是NSObject,它提供了很多运行时所必须的能力,例如内存分配等等。另外需要说明一点,单根类并不是Objective-C 语言规范要求的,它只不过是根据面向对象理论实现的。因此,所有Java 虚拟机的实现,这个单根类都是Object,但是在Objective-C 中,这就是与类库相关的了:在Cocoa 中,这个单根类是NSObject,而在gcc 的实现里则是Object。
严格说来,每一个类都应该是NSObject 的子类(相比之下,Java 应该说,每一个类都必须是Object 的子类),因此使用NSObject * 类型应该可以指到所有类对象的指针。但是,实际上我们使用的是id 类型。这个类型更加简短,更重要的是,id 类型是动态类型检查的,相比来说,NSObject * 则是静态类型检查。Objective-C 里面没有泛型,那么,我们就可以使用id 很方便的实现类似泛型的机制了。在Objective-C 里面,指向空的指针应该声明为nil,不能是NULL。这两者虽然很相似但并不可以互换。一个普通的 C 指针可以指向NULL,但是Objective-C 的类指针必须指向nil。正如前文所说,Objective-C 里面,类也是对象(元类Meta-Class 的对象)。nil 所对应的类就是Nil。
类声明
属性和方法
在Objective-C 里面,属性attributes 被称为实例数据instance data,成员函数member functions 被称为方法methods。如果没有特殊说明,在后续文章中,这两组术语都会被混用,大家见谅。
在C++ 中,属性和成员函数都在类的花括号块中被声明。方法的实现类似于 C 语言,只不过需要有作用于指示符(Foo::)来说明这个函数属于哪个类。
Objective-C 中,属性和方法必须分开声明。属性在花括号中声明,方法要跟在下面。它们的实现要在@implementation 块中。
这是与C++ 的主要不同。在Objective-C 中,有些方法可以不被暴露在接口中,例如private 的。而C++ 中,即便是private 函数,也能够在头文件中被看到。简单来说,这种分开式的声明可以避免private 函数污染头文件。
实例方法以减号–开头,而static 方法以+ 开头。注意,这并不是UML 中的private 和public 的区别!参数的类
型要在小括号中,参数之间使用冒号: 分隔。
Objective-C 中,类声明的末尾不需要使用分号;。同时注意,Objective-C 的类声明关键字是@interface,而不是@class。@class 关键字只用于前向声明。最后,如果类里面没有任何数据,那么花括号可以被省略。
前向声明
为避免循环引用,C 语言有一个前向声明的机制,即仅仅告诉存在性,而不理会具体实现。C++ 使用class 关键字实现前向声明。在Objective-C 中则是使用@class 关键字;另外,还可以使用@protocol
关键字来声明一个协议(我们会在后面说到这个概念,类似于Java 里面的interface)。
访问可见性是面向对象语言的一个很重要的概念。它规定了在源代码级别哪些是可见的。可见性保证了类的封装性。
在C++ 中,属性和方法可以是private,protected 和public 的。默认是private。
在Objective-C 中,只有成员数据可以是private,protected 和public 的,默认是protected 。方法只能是public 的。然而,我们可以在@implementation 块中实现一些方法,而不在@interface 中声明;或者是使用分类机制(class categories)。这样做虽然不能阻止方法被调用,但是减少了暴露。不经过
声明实现一些方法是Objective-C 的一种特殊属性,有着特殊的目的。我们会在后面进行说明。
Objective-C 中的继承只能是public 的,不可以是private 和protected 继承。这一点,Objective-C 更像Java 而不是C++。
static 属性
Objective-C 中不允许声明static 属性。但是,我们有一些变通的方法:在实现文件中使用全局变量(也可以添加static 关键字来控制可见性,类似 C 语言)。这样,类就可以通过方法访问到,而这样的全局变量的初始化可以在类的initialize 方法中完成。
从C++ 到Objective-C(4):类和对象(续)
作者: DevBean 日期: 2011 年03 月19 日发表评论 (3)查看评论
方法
Objective-C 中的方法与C++ 的函数在语法方面风格迥异。下面,我们就来讲述Objective-C 的方法。
原型、调用、实例方法和类方法
∙以–开头的是实例方法(多数情况下都应该是实例方法);以+ 开头的是类方法(相当于C++ 里面的static 函数)。Objective-C 的方法都是public 的;
∙返回值和参数的类型都需要用小括号括起来;
∙参数之间使用冒号:分隔;
∙参数可以与一个标签label 关联起来,所谓标签,就是在: 之前的一个名字。标签被认为是方法名字的一部分。这使得方法比函数更易读。事实上,我们应该始终使用标签。注意,第一个参数没有标签,通常它的标签就是指的方法名;
∙方法名可以与属性名相同,这使getter 方法变得很简单。
C++
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论