从 C++ 到 Objective-C(3):类和对象

来源:互联网 发布:大数据与国家安全 编辑:程序博客网 时间:2024/05/28 11:48

作者: DevBean 日期: 2011 年 03 月 19 日

 

 

既然是面向对象语言,类和对象显然是应该优先考虑的内容。鉴于本系列已经假定你已经熟悉 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++Objective-C
class Foo{    double x;    public:    int f(int x);    float g(int x, int y);}; int Foo::f(int x) {...} float Foo::g(int x, int y) {...}
@interface Foo : NSObject{    double x;} -(int)   f:(int)x;-(float) g:(int)x :(int)y; @end @implementation Foo -(int)   f:(int)x {...}-(float) g:(int)x :(int)y {...} @end

在 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++
//In file Foo.h #ifndef __FOO_H__#define __FOO_H__ class Bar; //forward declaration class Foo{    Bar* bar;public:    void useBar(void);}; #endif
//In file Foo.cpp #include "Foo.h"#include "Bar.h" void Foo::useBar(void){    ...}

 

Objective-C
//In file Foo.h @class Bar; //forward declaration @interface Foo : NSObject{    Bar* bar;} -(void) useBar; @end
//In file Foo.m #import "Foo.h"#import "Bar.h" @implementation Foo -(void) useBar{    ...} @end

private,protected 和 public

访问可见性是面向对象语言的一个很重要的概念。它规定了在源代码级别哪些是可见的。可见性保证了类的封装性。

C++Objective-C
class Foo{public:    int x;    int apple();protected:    int y;    int pear();private:    int z;    int banana();};
@interface Foo : NSObject{@public:    int x;@protected:    int y;@private:    int z;} -(int) apple;-(int) pear;-(int) banana; @end

在 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 方法中完成。

 

 

 

 

本文来自 DevBean's World:http://www.devbean.info。
转载时请标明文章原始出处:http://www.devbean.info/2011/03/from_cpp_to_objc_3/。

原创粉丝点击