object-c(2023最新object-c百科介绍)

由网友(北海未暖)分享简介:Objective-C是1种正在C的根蒂根基上插手面向对于象特征扩充而成的编程言语,凡是称为jObC以及较罕用的 Objective C或者ObjC。正在1定水平上,可以把 Objective-C当作是ANSI版原C言语的1个起散,它撑持不异的C言语基原语法,异时它还扩大了尺度的 ANSI C言语的语法,包孕界说类、要领以及属性。固然...

Objective-C是一种在C的基础上加入面向对象特性扩充而成的编程语言,通常称为jObC和较少用的 Objective C或ObjC。在一定程度上,可以把 Objective-C看成是ANSI版本C语言的一个起集,它支持相同的C语言基本语法,同时它还扩展了标准的 ANSI C语言的语法,包括定义类、方法和属性。当然还有其他一些结构的完善和拓展,如类别(Category)的出现。[1]

中文名

Objective-C

发明者

布莱德·确斯

别称

Objective-C

适用

IOS开发

发展历程及变化

如何往Excel中插入音乐

1980年初,布莱德·确斯( Brad Cox)发明了Objective-C,它是基于Smalltalk-80而发展起来的。Objective-C建立在C语言之上,意味着它是在C语言基础上添加了扩展而创造出来的能够创建和操作对象的一门新的程序设计语言。对Objective-C最主要的描述是1986年出版的Object-orientedProgramming,An Evolutionary Approach.

1988年,NeXT Sofiware公司开发出了Objective-C的语言库,并且开发了一个名为NEXTSTEP的开发环境。

1996年,苹果公司收购了NeXT Sofiware公司,然后把NEXTSTEP/OPENSTEP环境变成苹果操作系统下一个主要发行版本OS X的基础,这个开发环境的该版本被苹果公司称为Cocoa。

2006年,苹果公司发布了Objective-C 2.0,该版本增加了现代的垃圾收集语法改进、运行时性能改进和64位支持等功能。

2007年10月发布的Mac OS X v10.5中包含了Objective-C 2.0的编译器。[1]

Objective-C是GCC的一个前端,它可以编译混合了C++与Objective-C语法的源文件。

Objective-C是C的扩展。下面列出了两者的区别:

·Objective-C不支持多重继承(同Java和Smalltalk),而C++支持多重继承。

·C++类不能从Objective-C类继承,反之亦然。

·Objective-C是动态定型(Dynamicaly Typed),所以它的类库比C++要容易操作。Objective-C在运行时可以允许根据字符串名字来访问方法和类,还可以动态连接和添加类。

·C++跟从面向对象编程里的Simula 67( -种早期00语言)学派,而Objective-C属于Smalltalk学派。

·在C++里,对象的静态类型决定是否可以发送消息给它;而对Obj ective-C来说,由动态类型来决定。

·Objective-C定义内部不能定义C++命名空间。

·Objective-C类的成员变量不能包括不含默认构造函数和/或含有虚方法的C++类对象,但使用CH-类指针并无此限制(可以在-init方法中对其进行初始化)。

·C++“传递值”的特性不能用在Objective-C对象上,而只能传递其指针。

·Objective-C声明不能存在C++模板声明中,反之亦然,但Objective-C类型可以用在C++模板的参数中。

·Objective-C和C++的错误处理语句不同,各自的语句只能处理各自的错误。

·Objective-C错误使得C++对象被退出时,C++析构函数不会被调用。新的64位运行时解决了这个问题。

·Simula 67学派更安全,因为大部分错误可以在编译时查出;而Smalltalk学派更灵活,如一些Smalltalk看来无误的程序拿到Simualr 67那里就无法通过。[1]

语言性能与分析

Objective-C是非常“实际”的语言。它用一个很小的、用C写成的运行库,使得应用程序的大小增加很少,与此相比,大部分OO系统需要极大的虚拟机来执行。Objective-C写成的程序通常不会比其源代码和函式库(通常无须包含在软件发行版本中)大太多,不会像Smalltalk系统,即使只是打开一个窗口也需要占用极大的内存。由于Objective-C的动态类型特征,Objective-C不能对方法进行内联(inline)一类的优化,使得Objective.C的应用程序一般比类似的C或C++程序更小。

Objective-C较强的编译器适应性。Objective-C可以在现存C编译器基础上实现,而不需要编写一个全新的编译器。这个特性使得Objective-C能利用大量现存的C代码、库、工具和编程思想等资源。现存C库可以用Obj ective-C包装器来提供一个Objective-C使用的00风格界面包装,这些特性极大地降低了进入Objective-C的门槛。

Objective-C垃圾回收机制的引进。最初Objective-C不支持垃圾回收机制。在Apple发布的xCode4中已经支持自动释放功能,严格而言,应该称为“垃圾回收”。因为两者机制不同,在xCode4中的自动释放,也就是ARC (Automatic Reference Counting)机制,是不需要用户手动去释放一个对象的,而是在编译期间,编译器会自动帮助人们添加那些以前经常写的[NSObject release]。苹果公司在其Mac OS X 10.5中也提供了这种实现。

Objective-C新的命名规则应用。Objective-C不包括命名空间机制,处理这个问题的方法是程序设计师必须在其类别名称加上前缀,由于前缀往往较短(相比命名空间),这时常引致冲突。2007年,在Cocoa编程环境中,所有Mac OS X类别和函式均有NS作为前缀,如NSObject或NSButton来清楚分别它们属于Mac OS X核心;使用NS是由于这些类别的名称是在NeXTSTEP开发时定下的。

Objective-C独有个性。虽然Objective-C是C的严格超集,但它也不视C的基本类型为第一级的对象。和C++不同,Objective-C不支援运算子多载(它不支持ad-hoc多型)。亦与C++不同,但和Java相同,Objective-C只容许物件继承一个类别(不设多重继承)。Categories和protocols不但可以提供很多多重继承的好处,而且没有很多缺点,如额外执行时间过重和二进制不兼容。

由于Objective-C使用动态运行时类型,而且所有的方法都是函数调用(有时甚至连系统调用如syscalls也如此),很多常见的编译时的性能优化方法都不能应用于Obj ective-C(例如,内联函数、常数传播、交互式优化、纯量取代与聚集等),这使得Objective-C性能劣于类似的对象抽象语言(如CH)。不过Objective-C的拥护者认为既然Objective-C运行时消耗较大,Objective-C不该应用于C++或Java常见的底层抽象。[1]

语法

Objective-C是C语言的严格超集——任何C语言程序不经修改就可以直接通过Objective-C编译器,在Objective-C中使用C语言代码也是完全合法的。Objective-C被描述为盖在C语言上的薄薄一层,因为Objective-C的原意就是在C语言主体上加入面向对象的特性。Objective-C的面向对象语法源于Smalltalk消息传递风格。所有其他非面向对象的语法,包括变量类型,预处理器(preprocessing),流程控制,函数声明与调用皆与C语言完全一致。但有些C语言语法合法代码在objective-c中表达的意思不一定相同,比如某些布尔表达式,在C语言中返回值为true,但在Objective-C若与yes直接相比较,函数将会出错,因为在Objective-C中yes的值只表示为1。

HelloWorld

这里示范了一个基础的Hello World程序。基于Xcode 4.3.1:

消息传递

Objective-C最大的特色是承自Smalltalk的消息传递模型(message passing),此机制与今日C++式之主流风格差异甚大。Objective-C里,与其说对象互相调用方法,不如说对象之间互相传递消息更为精确。此二种风格的主要差异在于调用方法/消息传递这个动作。C++里类别与方法的关系严格清楚,一个方法必定属于一个类别,而且在编译时(compile time)就已经紧密绑定,不可能调用一个不存在类别里的方法。但在Objective-C,类别与消息的关系比较松散,调用方法视为对对象发送消息,所有方法都被视为对消息的回应。所有消息处理直到运行时(runtime)才会动态决定,并交由类别自行决定如何处理收到的消息。也就是说,一个类别不保证一定会回应收到的消息,如果类别收到了一个无法处理的消息,程序只会抛出异常,不会出错或崩溃。

C++里,送一个消息给对象(或者说调用一个方法)的语法如下:

Objective-C则写成:

此二者并不仅仅是语法上的差异,还有基本行为上的不同。

此二种风格各有优劣。C++强制要求所有的方法都必须有对应的动作,且编译期绑定使得函数调用非常快速。缺点是仅能借由virtual关键字提供有限的动态绑定能力。Objective-C天生即具备鸭子类型之动态绑定能力,因为运行期才处理消息,允许发送未知消息给对象。可以送消息给整个对象集合而不需要一一检查每个对象的类型,也具备消息转送机制。同时空对象nil接受消息后默认为不做事,所以送消息给nil也不用担心程序崩溃。

类的定义与实现

Objective-C中强制要求将类的定义(interface)与实现(implementation)分为两个部分。

类的定义文件遵循C语言之惯例以.h为后缀,实现文件以.m为后缀。

Interface

定义部分,清楚定义了类的名称、成员变量和方法。 以关键字@interface作为开始,@end作为结束。

方法前面的 +/- 号代表函数的类型:加号(+)代表类方法(class method),不需要实例就可以调用,与C++ 的静态函数(static member function)相似。减号(-)即是一般的实例方法(instance method)。

这里提供了一份意义相近的C++语法对照,如下:

Objective-C定义一个新的方法时,名称内的冒号(:)代表参数传递,不同于C语言以数学函数的括号来传递参数。Objective-C方法使得参数可以夹杂于名称中间,不必全部附缀于方法名称的尾端,可以提高程序可读性。设定颜色RGB值的方法为例:

这个方法的签名是setColorToRed:Green:Blue:。每个冒号后面都带着一个float类别的参数,分别代表红,绿,蓝三色。

Implementation

实现区块则包含了公开方法的实现,以及定义私有(private)变量及方法。 以关键字@implementation作为区块起头,@end结尾。

值得一提的是不只Interface区块可定义实体变量,Implementation区块也可以定义实体变量,两者的差别在于访问权限的不同,Interface区块内的实体变量默认权限为protected,宣告于implementation区块的实体变量则默认为private,故在Implementation区块定义私有成员更符合面向对象之封装原则,因为如此类别之私有信息就不需曝露于公开interface(.h文件)中。

创建对象

Objective-C创建对象需通过alloc以及init两个消息。alloc的作用是分配内存,init则是初始化对象。 init与alloc都是定义在NSObject里的方法,父对象收到这两个信息并做出正确回应后,新对象才创建完毕。以下为范例:

在Objective-C 2.0里,若创建对象不需要参数,则可直接使用new

仅仅是语法上的精简,效果完全相同。

若要自己定义初始化的过程,可以重写init方法,来添加额外的工作。(用途类似C++ 的构造函数constructor)

协议Protocol

协议是一组没有实现的方法列表,任何的类均可采纳协议并具体实现这组方法。

Objective-C在NeXT时期曾经试图引入多重继承的概念,但由于协议的出现而没有实现之。

协议类似于Java与C#语言中的“接口”。在Objective-C中,有两种定义协议的方式:由编译器保证的“正式协议”,以及为特定目的设定的“非正式协议”。

非正式协议为一个可以选择性实现的一系列方法列表。非正式协议虽名为协议,但实际上是挂于NSObject上的未实现分类(Unimplemented Category)的一种称谓,Objetive-C语言机制上并没有非正式协议这种东西,OSX 10.6版本之后由于引入@optional关键字,使得正式协议已具备同样的能力,所以非正式协议已经被废弃不再使用。

正式协议类似于Java中的"接口",它是一系列方法的列表,任何类都可以声明自身实现了某个协议。在Objective-C 2.0之前,一个类必须实现它声明符合的协议中的所有方法,否则编译器会报告错误,表明这个类没有实现它声明符合的协议中的全部方法。Objective-C 2.0版本允许标记协议中某些方法为可选的(Optional),这样编译器就不会强制实现这些可选的方法。

协议经常应用于Cocoa中的委托及事件触发。例如文本框类通常会包括一个委托(delegate)对象,该对象可以实现一个协议,该协议中可能包含一个实现文字输入的自动完成方法。若这个委托对象实现了这个方法,那么文本框类就会在适当的时候触发自动完成事件,并调用这个方法用于自动完成功能。

Objective-C中协议的概念与Java中接口的概念并不完全相同,即一个类可以在不声明它符合某个协议的情况下,实现这个协议所包含的方法,也即实质上符合这个协议,而这种差别对外部代码而言是不可见的。正式协议的声明不提供实现,它只是简单地表明符合该协议的类实现了该协议的方法,保证调用端可以安全调用方法。

语法

协议以关键字@protocol作为区块起始,@end结束,中间为方法列表。

这是一个协议的例子,多线程编程中经常要确保一份共享资源同时只有一个线程可以使用,会在使用前给该资源挂上锁 ,以上即为一个表明有“锁”的概念的协议,协议中有两个方法,只有名称但尚未实现。

下面的SomeClass宣称他采纳了Locking协议:

一旦SomeClass表明他采纳了Locking协议,SomeClass就有义务实现Locking协议中的两个方法。

由于SomeClass已经确实遵从了Locking协议,故调用端可以安全的发送lock或unlock消息给SomeClass实体变量,不需担心他没有办法回应消息。

插件是另一个使用抽象定义的例子,可以在不关心插件的实现的情况下定义其希望的行为。

动态类型

类似于Smalltalk,Objective-C具备动态类型:即消息可以发送给任何对象实体,无论该对象实体的公开接口中有没有对应的方法。对比于C++这种静态类型的语言,编译器会挡下对(void*)指针调用方法的行为。但在Objective-C中,你可以对id发送任何消息(id很像void*,但是被严格限制只能使用在对象上),编译器仅会发出“该对象可能无法回应消息”的警告,程序可以通过编译,而实际发生的事则取决于运行期该对象的真正形态,若该对象的确可以回应消息,则依旧运行对应的方法。

一个对象收到消息之后,他有三种处理消息的可能手段,第一是回应该消息并运行方法,若无法回应,则可以转发消息给其他对象,若以上两者均无,就要处理无法回应而抛出的例外。只要进行三者之其一,该消息就算完成任务而被丢弃。若对“nil”(空对象指针)发送消息,该消息通常会被忽略,取决于编译器选项可能会抛出例外。

虽然Objective-C具备动态类型的能力,但编译期的静态类型检查依旧可以应用到变量上。以下三种声明在运行时效力是完全相同的,但是三种声明提供了一个比一个更明显的类型信息,附加的类型信息让编译器在编译时可以检查变量类型,并对类型不符的变量提出警告。

下面三个方法,差异仅在于参数的形态:

id形态表示参数“foo”可以是任何类的实例。

id表示“foo”可以是任何类的实例,但必须采纳“aProtocol”协议。

该声明表示“foo”必须是“NSNumber”的实例。

动态类型是一种强大的特性。在缺少泛型的静态类型语言(如Java 5以前的版本)中实现容器类时,程序员需要写一种针对通用类型对象的容器类,然后在通用类型和实际类型中不停的强制类型转换。无论如何,类型转换会破坏静态类型,例如写入一个“整数”而将其读取为“字符串”会产生运行时错误。这样的问题被泛型解决,但容器类需要其内容对象的类型一致,而对于动态类型语言则完全没有这方面的问题。

转发

Objective-C允许对一个对象发送消息,不管它是否能够响应之。除了响应或丢弃消息以外,对象也可以将消息转发到可以响应该消息的对象。转发可以用于简化特定的设计模式,例如观测器模式或代理模式。

Objective-C运行时在Object中定义了一对方法:

  • 转发方法:

响应方法:

希望实现转发的对象只需用新的方法覆盖以上方法来定义其转发行为。无需重写响应方法performv::,由于该方法只是单纯的对响应对象发送消息并传递参数。其中,SEL类型是Objective-C中消息的类型。

类别Category

在Objective-C的设计中,一个主要的考虑即为大型代码框架的维护。结构化编程的经验显示,改进代码的一种主要方法即为将其分解为更小的片段。Objective-C借用并扩展了Smalltalk实现中的“分类”概念,用以帮助达到分解代码的目的。

一个分类可以将方法的实现分解进一系列分离的文件。程序员可以将一组相关的方法放进一个分类,使程序更具可读性。举例来讲,可以在字符串类中增加一个名为“拼写检查”的分类,并将拼写检查的相关代码放进这个分类中。

进一步的,分类中的方法是在运行时被加入类中的,这一特性允许程序员向现存的类中增加方法,而无需持有原有的代码,或是重新编译原有的类。例如若系统提供的字符串类的实现中不包含拼写检查的功能,可以增加这样的功能而无需更改原有的字符串类的代码。

在运行时,分类中的方法与类原有的方法并无区别,其代码可以访问包括私有类成员变量在内的所有成员变量。

若分类声明了与类中原有方法同名的函数,则分类中的方法会被调用。因此分类不仅可以增加类的方法,也可以代替原有的方法。这个特性可以用于修正原有代码中的错误,更可以从根本上改变程序中原有类的行为。若两个分类中的方法同名,则被调用的方法是不可预测的。

其它语言也尝试了通过不同方法增加这一语言特性。TOM在这方面走的更远,不仅允许增加方法,更允许增加成员变量。也有其它语言使用面向声明的解决方案,其中最值得注意的是Self语言。

C#与Visual Basic.NET语言以扩展函数的与不完全类的方式实现了类似的功能。Ruby与一些动态语言则以"monkey patch"的名字称呼这种技术。

使用分类的例子

这个例子创建了Integer类,其本身只定义了integer属性,然后增加了两个分类Arithmetic与Display以扩展类的功能。虽然分类可以访问类的私有成员,但通常利用属性的访问方法来访问是一种更好的做法,可以使得分类与原有类更加独立。这是分类的一种典型应用—另外的应用是利用分类来替换原有类中的方法,虽然用分类而不是继承来替换方法不被认为是一种好的做法。

语言变化

Objective-C++是GCC的一个前端,它可以编译混合了C++与Objective-C语法的源文件。Objective-C++是C++的扩展,类似于Objective-C是C的扩展。由于在融合C++与Objective-C两种语言的特性方面没有做特别的工作,因此有以下限制:

  • C++类不能从Objective-C类继承,反之亦然。
  • Objective-C定义内部不能定义C++名字空间。
  • Objective-C类的成员变量不能包括不含默认构造函数和/或含有虚方法的C++类对象,但使用C++类指针并无如此限制(可以在 -init方法中对之进行初始化)。
  • C++“传递值”的特性不能用在Objective-C对象上,而只能传递其指针。
  • Objective-C声明不能存在在C++模板声明中,反之亦然。但Objective-C类型可以用在C++模板的参数中。
  • Objective-C和C++的错误处理语句不同,各自的语句只能处理各自的错误。
  • Objective-C错误使得C++对象被退出时,C++析构函数不会被调用。新的64位运行时解决了这个问题。

Objective-C2.0

在2006年7月苹果全球开发者会议中,Apple宣布了“Objective-C 2.0”的发布,其增加了“现代的垃圾收集,语法改进,运行时性能改进,以及64位支持”。2007年10月发布的Mac OS X v10.5中包含了Objective-C 2.0的编译器。

垃圾收集

Objective-C 2.0提供了一个可选的垃圾收集器。在向后兼容模式中,Objective-C运行时会将引用计数操作,例如“retain”与“release”变为无操作。当垃圾收集启用时,所有的对象都是收集器的工作对象。普通的C指针可以以“__strong”修饰,标记指针指向的对象仍在使用中。被标记为“__weak”的指针不被计入收集器的计数中,并在对象被回收时改写为“nil”。iOS上的Objective-C 2.0实现中不包含垃圾收集器。垃圾收集器运行在一个低优先级的后台线程中,并可以在用户动作时暂停,从而保持良好的用户体验。

属性

Objective-C 2.0引入了新的语法以声明变量为属性,并包含一可选定义以配置访问方法的生成。属性总是为公共的,其目的为提供外部类访问(也可能为只读)类的内部变量的方法。属性可以被声明为“readonly”,即只读的,也可以提供储存方法包括“assign”,“copy”或“retain”(简单的赋值、复制或增加1引用计数)。默认的属性是原子的,即在访问时会加锁以避免多线程同时访问同一对象,也可以将属性声明为“nonatomic”(非原子的),避免产生锁。

ModernObjective-C

苹果公司在 WWDC2012 大会上介绍了大量 Objective-C 的新特性,能够让程序员更加高效地编写代码,这些新特性在 Xcode4.4 版本中已经可以使用。

  • Object Literals
  • 默认生成 @synthesize 代码
  • 遍历元素
  • Subscripting Methods

语言分析

Objective-C是非常“实际”的语言。它用一个很小的、用C写成的运行库,使得应用程序的大小增加很少,与此相比,大部分OO系统需要极大的运行时虚拟机来执行。ObjC写成的程序通常不会比其源代码和库(通常无需包含在软件发行版本中)大太多,不会像Smalltalk系统,即使只是打开一个窗口也需要大量的容量。由于Obj-C的动态类型特征,Obj-C不能对方法进行内联(inline)一类的优化,使得Obj-C的应用程序一般比类似的C或C++程序更大。

Obj-C可以在现存C编译器基础上实现(在GCC中,Obj-C最初作为预处理器引入,后来作为模块存在),而不需要编写一个全新的编译器。这个特性使得Obj-C能利用大量现存的C代码、库、工具和编程思想等资源。现存C库可以用Obj-C包装器来提供一个Obj-C使用的OO风格界面包装。

以上这些特性极大地降低了进入Obj-C的门槛,这是1980年代Smalltalk在推广中遇到的最大问题。

争议

Objective-C的最初版本并不支持垃圾回收(garbage collection)。在当时这是争论的焦点之一,很多人考虑到Smalltalk回收时有漫长的“死亡时间”,令整个系统失去功用,Objective-C为避免此问题才不拥有这个功能。某些第三方版本加入了这个功能(尤是GNUstep),苹果公司也在其Mac OS X 10.5中提供了实现。

另一个广受批评的问题是ObjC不包括名字空间机制(namespace mechanism)。取而代之的是程序员必须在其类别名称加上前缀,由于前缀往往较短(相比名字空间),这时常引致冲突。在2007年,在Cocoa编程环境中,所有Mac OS X类别和函数均有“NS”作为前缀,例如NSObject或NSButton来清楚分辨它们属于Mac OS X核心;使用“NS”是由于这些类别的名称在NeXTSTEP开发时定下。

虽然Objective-C是C的严格超集,但它也不视C的基本类型为第一级的对象。

和C++不同,Objective-C不支持运算符重载(它不支持ad-hoc多态)。亦与C++不同,但和Java相同,Objective-C只容许对象继承一个类别(不设多重继承)。Categories和protocols不但可以提供很多多重继承的好处,而且没有很多缺点,例如额外运行时间过重和二进制不兼容。

由于Obj-C使用动态运行时类型,而且所有的方法都是函数调用(有时甚至连系统调用(syscalls)也如此),很多常见的编译时性能优化方法都不能应用于Obj-C(例如:内联函数、常数传播、交互式优化、纯量取代与聚集等)。这使得Obj-C性能劣于类似的对象抽象语言(如C++)。不过Obj-C拥护者认为Obj-C本就不应应用于C++或Java常见的底层抽象,Obj-C的应用方向是对性能要求不大的应用

优点及缺点

Objective-C是非常“实际”的语言。它使用一个用C写成、很小的运行库,只会令应用程序的大小增加很小,和大部分OO系统使用极大的VM执行时间会取代了整个系统的运作相反,ObjC写成的程序通常不会比其原始码大很多。而其库函数(通常没附在软件发行本)亦和Smalltalk系统要使用极大的内存来开启一个窗口的情况相反。 Objective-C的最初版本并不支持垃圾回收。在当时这是争论的焦点之一,很多人考虑到Smalltalk回收时有漫长的“死亡时间”,令整个系统失去作用。Objective-C为避免此问题才不拥有这个功能。虽然某些第三方版本已加入这个功能(尤是GNUstep),Apple在其Mac OS X 10.3中仍未引入这个功能。 另一个问题是ObjC不包括命名空间机制(namespace mechanism)。取而代之的是程序设计师必须在其类别名称加上前缀,时常引致冲突。在2004年,在Cocoa编程环境中,所有Mac OS X类别和函数均有“NS”作为前缀,例如NSObject或NSButton来清楚分辨它们属于Mac OS X核心;使用“NS”是由于这些类别的名称在NeXTSTEP开发时定下。 虽然Objective-C是C的母集,但它也不视C的基本型别为第一级的对象。 和C++不同,Objective-C不支持运算子重载(它不支持ad-hoc多型)。亦与C++不同,但和Java相同,Objective-C只容许对象继承一个类(不设多重继承)。Categories和protocols不但可以提供很多多重继承的好处,而且没有很多缺点,例如额外执行时间过重和二进制不兼容。

和C的比较

  1. Objective-C是iOS的编译语言。
  2. 与C++的不同之处有:
    • OC中所有的类都必须继承自NSObject。
    • OC中所有对象都是指针的形式。
    • OC用self代替this。
    • OC使用id代替void*。
    • OC使用nil表示NULL
    • OC只支持单继承。
    • OC使用YES/NO表示TRUE/FALSE
    • OC使用#import代替#include
    • OC中用消息表示类的方法,并采用[aInstance method:argv]调用形式。
    • OC支持反射机制
    • OC支持Dynamic Typing, Dynamic Binding和Dynamic Loading。
  3. 与C++的相同之处有:
    • 与C共享的部分一致。
    • 可以使用assert(BOOL), 一般用NSCParameterAssert(BOOL)代替。
  4. OC中的命名前缀说明:
    • NS-:NextStep
    • CF-:Core Foundation
    • CA-:Core Animation
    • CG-:Core Graphics
    • UI-:User Interface
  5. OC中的消息特殊性:
    • 调用消息的类可以不知道如何响应这个消息。如果它不知道如何处理这个消息,它会自动的将这个消息转给其他的类,比如它的父类。
    • 调用消息的类可以是nil。在C++中,在使用类方法之前,我们都需要检查对象是否为空,所以在实现析构函数的时候,常会有如下的代码,如if (var) { delete var; }但是在objective c中,我们就可以直接写[var release];即使var == nil, 也不会有问题。
  6. OC中的函数声明格式有:
    • -/+ (return type) function_name;
    • -/+ (return type) function_name : (parameter type) parameter;
    • -/+ (return type) function_name : (parameter type) parameter1otherParameter: (parameter_type) parameter2
    • 以上参数说明:-表示一般函数,+表示静态函数。otherParameter是参数的别名(第一个参数的别名省略),在函数调用时方便指定。
  7. OC中的构造/析构函数
    • OC中的init()/release()对应于C++的构造/析构函数。alloc()/dealloc()也就对应于C++的new和delete,其中的dealloc()由于引用计数的自动调用而不用手动调用。
    • OC中父类的init()/release()函数需要子类的手动调用。而且每次都必须调用。不同于C++的自动调用。
    • 构造函数(- (id) init)调用形如:CSample* pSample=[CSample alloc] init];其中alloc(+ (id) alloc)是继承来的static函数,init是继承来的一般函数,如重写一般函数时,则相当于C++的覆盖(不带参数)或重载(带参数)。
    • 析构函数(- (void) release)将引用计数减1,当=0时父类的release()会自动调用dealloc(- (void) dealloc);
  8. 当OC没有数据成员时,可省略{},建议保留。
  9. 继承下来的方法,如:-(id) init可以头文件中省略,建议保留
  10. OC中只有数据成员的访问限制,没有方法的访问限制。
    • 同C++一样,数据成员有三种访问限制public, protected, private,缺省是protected。
    • 示例:@interface AccessExample: NSObject {
      @public
      int publicVar;
      @protected
      int protectedVar;
      @private
      int privateVar;
      }
      @end
    • 方法的访问限制可通过Category实现
    • 示例:@interface MyClass- (void) sayHello {NSLog(@"Hello");
      }
      @end

      @interface MyClass(Private)- (void) kissGoodbye;@end
  11. OC中没有类的静态变量,只有全局变量
  12. OC中的数组NSArray可以保存不同对象类型的数据。
  13. OC也支持runtime时的类型检查
    • - (BOOL) isKindOfClass: classObj
      用于判断该对象是否属于某个类或者它的子类
    • - (BOOL) isMemberOfClass: classObj
      用于判断该对象是否属于某个类(这里不包括子类)
    • - (BOOL) respondsToSelector: selector
      用于判断该对象是否能响应某个消息。这里,我们可以将@selector后面带的参数理解为C++中的函数指针。
      注意:1)不要忘了@ ;2)@selector后面用的是(),而不是[ ] ;3)要在消息名称后面跟:,无论这个消息是否带参数。如:[pSquare respondsToSelector:@selector(Set: andHeight:)]。
    • + (BOOL) instancesRespondToSelector: selector
      用于判断该类的对象是否能响应某个消息。这是一个静态函数。
    • -(id) performSelector: selector :调用对象的selector方法。
    • conformsToProtocol 类似于respondsToSelector ,用于动态检查某个对象是否遵守某个协议。
  14. Category:在没有源代码的情况下,为一个已经存在的类添加一些新的功能
    • 只能添加新的方法,不能添加新的数据成员
    • Category的名字必须是唯一的
  15. Protocol:相当于C++中的纯虚类
    • 形如:@interface MyDate: NSObject { } @end
    • 使用:MyDate * dat = [[MyDate alloc] init];id var = dat; [var print]。
    • 说明:我们首先声明了Printing 协议,任何遵守这个协议的类,都必须实现print 方法。在Objective C 中,我们通过<>来表示遵守某个协议。当某个类声明要遵守某个协议之后,它就必须在.m文件中实现这个协议中的所有方法。使用id 作为类型,而不是象C++中的Printing* var。
  16. IBOutlet, IBAction: 这两个东西其实在语法中没有太大的作用。如果你希望在Interface Builder中能看到这个控件对象,那么在定义的时候前面加上IBOutlet,在IB里就能看到这个对象的outlet,如果你希望在Interface Builder里控制某个对象执行某些动作,就在方法前面加上(IBAction)。
  17. 尽量避免在一行语句中进行两层以上的嵌套
  18. 消息转发:- (void) forwardInvocation: (NSInvocation*)anInvocation;

扩展的关键字

类型声明,类似于c++中的class,区别在于Object c中的声明与实现是强制分开的,@interface关键字用于类型的声明,包括数据成员、方法声明、属性等。方法的参数传递采用中缀符的形式,利用“:”分割参数名和被传递参数,类型的声明以@interface开头,以@end结束,通常一个类型的声明采用下面的结构:

@classsomeOtherObject //外部类型声明

@interfacesomeObject:NSObject //继承的类型

{

int i; //成员变量

}

-(id)someMethod:(int)someArg someOtherArgName:(int)someOtherArg; //对象的方法

+(id)someMethod:(int)someArg; //类方法

-(id)init; //初始化方法

@propertyint num; //属性

@end

@implementation

对应于@interface的类型声明,@implementation表示一个类型的实现过程,同样以@end结束,实现的格式通常如下:

@implementationsomeObject

-(id)someMethod:(int)someArg someOtherArgName:(int)someOtherArg

{

//实现代码

}

@synthesizenum=i; //将属性与变量进行对应

@end

new、alloc

Object C中的方法调用形式采用消息发送的方式,通常调用的形式如

[someObject someMethod:firstArg someOtherArgName:otherArg]

实例的初始化也采用消息发送的形式,可以简单的调用类型的new方法来获取一个实例对象,简单实例化的方法通常是:

someObject *obj = [someObjectnew]; //类的实例化

new方法的实际过程是调用allocinit方法,因此如果需要采用自定义的方法来初始化实例,则需要自己重写init方法,通常的初始化方式为:

someObject *obj = [[someObjectalloc] init]; //采用无参数的init实例化

someObject *obj = [[someObjectalloc] initWithArg:Arg]; //采用参数的实例化

@class

@class是一个前向引用声明,类似于C++中的friend友元声明,其作用是告诉编译器其后面的字段代表一个类型名称,尽管不知道类型的具体实现,但是只需要将其作为一个类型名称处理即可。通常在使用复合的结构时可以采用@class来减少头文件的相互引用,如果出现循环依赖,则需要依靠@class来避免引用的死循环。通常使用形式为:

@classsomeOtherObject;

@interfacesomeObject:NSObject

{

someOtherObject *obj;

}

@end

@property

尽管可以使用obj->arr的形式去强制读取对象的成员变量,但是良好的编程形式是对外界提供成员变量的读写接口。@property关键字提供了外界对成员变量的访问接口,其本质是为某一个属性提供set和get操作。根据不同的需要,可以添加readonly(只读,相当于只添加get不添加set方法)或者readwrite(读写,如果不添加则为默认);还有三种赋值方式可选:assign(直接赋值,通常用于基本类型),retain(释放旧值,增加新的retaincount),copy(常用于字符串,生成一个新的拷贝)。通常使用的方式如下:

@interfacesomeObject:NSObject

{

int i; //成员变量

}

@property(assign,readonly) int num; //属性

@end

@synthesize

@property对应,将一个外在属性与成员变量相关联,定义在@implementation中,如果属性名与变量名一致则可以省略变量名。常用方法:

@implementationsomeObject

@synthesizenum=i;//如果属性名也为i,则可以直接写为@synthesizei

@end

内存管理

Object C采用引用计数的方式进行内存管理,由于所有的对象都继承于NSObject,因此所有的对象都可以接受NSObject的三个方法:

-(id)retain;

-(void)release;

-(unsigned)retainCount;

retain方法将对象的引用计数加一并返回该对象,release将引用计数减一,retainCount方法返回对象当前的引用计数。当采用new、alloc、copy方法创建一个对象时,它的引用计数被置为1,如果程序中对该对象进行操作,则应根据需要,通过调用retain和release方法来保证该对象在不需要的时候被清除。当一个对象的引用计数被置为0后,系统会自动向对象发送一个dealloc消息,将其占有的资源释放。通常情况下,如果一个对象的初始化过程调用了其他资源,则应该重写改对象的dealloc过程,保证在对象的销毁期正确释放这些资源。

为了更加方便的进行能存管理,cocoa中提供了一个自动释放池(autorelease pool)的概念,每一个类都继承了一个autorelease方法,当调用对象的autorelease方法时,改对象会被加入到开始创建的自动释放池中。当程序进行到不再需要自动释放池中的对象时,将自动释放池释放的时候会向池中的所有对象发送一个release消息,从而保证不再需要的对象被正确的释放。通常的用法如下:

NSAutoreleasePool *pool;

pool = [[NSAutoreleasePool alloc] init];

someObject * obj = [[someObject alloc] init];

[obj autorelease]; //加入自动释放池

//其他代码

[pool release]; //执行该语句时,系统会向池内所有的对象发送release消息;在这个例子中,如果对obj进行的其他retain操作和release操作保持一致的话,则会将obj的引用计数变为0,从而调用它的dealloc方法进行资源释放

Object C进行内存管理的3条规则是:

  1. 如果使用new、alloc或copy操作获得一个对象,则该对象的保留计数器值为1
  2. 如果通过任何其他方法获得一个对象,则假设该对象的保留计数器值为1,而且已经被设置为自动释放
  3. 如果保留了某个对象,则必须保持retain方法和release方法的使用次数相等。

类别

类别是为现有的类提供一个新的方法的方法,即使没有一个类的源代码,仍然可以向类中添加一个方法以方便使用。类别的主要目的有3个:将类的实现分散到多个不同的文件或框架中,创建对私有方法的前向引用,向对象添加非正式协议。

类别的声明方法:

@interfacesomeObject (someProtocal)

-(void)someMethod;

@end

类别的实现方法:

@implementationsomeObject(someProtocal)

-(void)someMethod

{

}

@end

@protocol

Object C中的协议类似于java中的接口,通过@protocol关键字定义一个或多个需要遵从协议的对象实现的方法,协议定义的方法:

@protocolsomeProtocol

-(void)someMethod;

@end

采用协议的方法是在类声明时使用尖括号注明其需要使用的协议:

@interfacesomeObject:NSObject

在类实现时需要将协议中规定的方法都予以实现。

Object C 2.0增加了2个新的协议修饰符@optional@required,可以规定协议中的方法是否为必须实现的方法。

阅读全文

相关推荐

最新文章