个性化阅读
专注于IT技术分析

Objective-C类和对象 – Objective-C开发教程

上一章Objective-C开发教程请查看:Objective-C命令行参数

Objective-C是C语言的超集或一个扩展,这意味着你可以在OC中进行C语言风格的编程,同时OC对C的扩展是为了实现OOP面向对象编程。OOP编程是以类class为中心,类通常是对数据成员和操作算法的封装,这个对于C语言也是可以做到的,但是OC的风格相对更方便而已。

OOP编程仅仅有数据封装是不够的,加入之后你对某个算法有不同的实现,究竟是删了/注释这份代码还是另外重新实现更好,当然后者更好了,这就是多态的功能。这章我们先讨论OC的类和对象的使用,接着的章节我们会讨论到类的继承以及多态的使用。

Objective-C类和对象的基本特点

  • OC使用@interface声明一个类,使用@implementation实现一个类。
  • 所有的数据和操作算法都可以封装在一个类中。
  • OC中的对象用于接收消息,获取属性和调用方法都相当于向对象发送消息。
  • 实例对象包含所有实例变量。
  • 实例对象和实例变量的使用都有对应的范围限制。
  • 类隐藏一个对象的实现。
  • 属性用于提供类的实例对象在其它地方访问。

定义类

定义一个类就是定义一个新的数据类型,但是定义类不占用任何内存,它告诉编译器这个类有某些属性和操作方法,只有实例化一个类型的对象,这个对象会占用内存空间,也就是说,定义类和和之前说的声明变量和函数是类型的。

定义一个类使用@interface开始,以@end结束,中间是类的声明部分,主要是属性声明和方法声明。OC中定义任何一个类都要显式使用(:)继承一个指定的基类/父类,如果没有目标类要继承,则默认使用NSObject,这个类是所有类的超类,这个类提供所有类的一些基本操作,例如申请内存alloc以及初始化init。

下面定义一个Box类:

@interface Box:NSObject {
   // 实例变量, 私有属性, 只能在类中访问
   double length;   
   double breadth;  
}
@property(nonatomic, readwrite) double height;  // 属性,可以使用点操作符

@end

分配内存和初始化OC对象

一个类提供对象的基本框架,对象是一个实例,根据类的形式进行创建。一般来说,NSObject基类提供alloc方法来给对象分配内存(类似C语言的malloc),init方法用来初始化对象(在没有使用其它初始化函数的时候,这两步等价于使用一个new),如下例子:

Box *box1 = [[Box alloc]init];
Box *box2 = [Box new];

访问数据成员

可以使用直接成员访问操作符(.)访问类的对象属性。让我们用下面的例子来说明一下:

#import <Foundation/Foundation.h>

@interface Box:NSObject {
   double length;    // 长度
   double breadth;   // 宽度
   double height;    // 高度
}

@property(nonatomic, readwrite) double height;  // 属性
-(double) volume;
@end

@implementation Box

@synthesize height; 

-(id)init {
   self = [super init]; // 调用父类初始化方法, self为当前对象指针
   length = 1.0;
   breadth = 1.0;
   return self;
}

-(double) volume {
   return length*breadth*height;
}

@end

int main() { 
   Box *box1 = [[Box alloc]init];    
   Box *box2 = [[Box alloc]init];   

   double volume = 0.0;             
 
   box1.height = 5.0; 

   box2.height = 10.0;
  
   volume = [box1 volume];
   NSLog(@"Volume of Box1 : %f", volume);
   
   volume = [box2 volume];
   NSLog(@"Volume of Box2 : %f", volume);

   return 0;
}

OC中的属性

在Objective-C中引入了属性,以确保类的实例变量可以在类之外访问。

各个部分的属性声明如下:

  • 属性以@property开头,它是一个关键字
  • 然后是访问说明符,可用的说明符有:nonatomic或atomic、readwrite或readonly和strong、unsafe_unretain或weak。这取决于变量的类型。对于任何指针类型,我们都可以使用strong、unsafe_unretain或weak。类似地,对于其他类型,我们可以使用readwrite或readonly。
  • 然后是变量的数据类型。
  • 最后,属性名以分号结束。
  • 我们可以在实现类中添加synthesize语句,但是在最新的XCode中,合成部分由XCode负责,不需要包含synthesize语句。

只有使用属性我们才能访问类的实例变量,实际上,在内部为属性创建了getter和setter方法。

例如,假设我们有一个属性@property (nonatomic, readonly) BOOL isDone,在底层,创建了如下所示的setter和getter。

-(void)setIsDone(BOOL)isDone;
-(BOOL)isDone;

属性声明解释

第一个中是实例属性,只在@interface{}中进行声明,称为私有实例成员属性,只能在类内部使用,如果需要在外部使用可以使用一个方法实现间接访问,如果最好使用第二种属性的声明方式。

第二种是OC提供某些特殊处理的成员属性,声明语法为:

@property(参数说明符)类型 变量名;
例如:
@property(nonatomic, readwrite)int age;

其中参数说明符主要分为三类:

  • 1、储存特性:readwrite/readonly(读写/只读),readwrite产生setter/getter方法,readonly只产生getter方法,默认为readwrite。
  • 2、内出特性:assign/retain/copy/strong/weak(赋值/保留/复制/强/弱),assign是默认的方式,setter方法直接赋值。
  • retain是浅拷贝,复制对象地址,让目标对象和源对象同指向一个内存空间。
  • copy是深拷贝,从源对象复制多一份同样的内存空间。
  • strong,类似retain,多个指针指向同一个内存时,只要有一个指向该内存,内存就不会被释放。
  • weak,类似assign,多个指针指向同一个内存时,只要有一个不指向该内存,内存就会被释放。
  • 3、原子性:nonatomic/atomic(非原子性/原子性),默认为atomic。nonatomic禁止多线程,提高性能。atomic给getter和setter加锁,使多个线程能准确同步。
  • 4、可null性:默认unll_unspecified未指定,nullable对象可为空,nonnull对象不可为空,null_resettable,调用setter可传入nil,getter为空。

另外要注意的地方,使用默认值atomic有额外的性能耗费,若无必要,请使用nonatomic效率更高。

对应属性生成的getter和setter方法后,其属性名变成_name,如果要重写相关方法需要使用加下划线的属性。在类中使用属性也可以直接使用_name更方便,而使用self.访问属性相对耗时。

非ARC时assign是默认值,ARC下strong是默认值,可以忽略掉retain,因为retain和strong类似,这样我们只需关注strong、weak、assign和copy。

strong和retain都是指针拷贝,还有人在使用内存就不会被释放,对象引用计数加1。强制置为nil可以释放。

weak也是指针拷贝,对象引用计数不增加,但是只要有一个人不用了就被释放,不手动设置,自动销毁。

assign一般只用于修饰基本数据类型。

特别地,copy用于如NSString、NSArray、NSDictionary等,而NSMutableArray、NSMutablestring、NSMutableDictionary声明类型用strong。

如果所有属性都不为null,可以使用下面两个宏:

NS_ASSUME_NONNULL_BEGIN
@interface App : NSObject

@end
NS_ASSUME_NONNULL_END
赞(0)
未经允许不得转载:srcmini » Objective-C类和对象 – Objective-C开发教程

评论 抢沙发

评论前必须登录!