Object-C是C语言的超集,提供了面相对象和多态的功能。关键字interface相当于C++的class;关键字protocol相当于C++的interface;
类的声明与实现
头文件声明如下:
#ifndef testClass_h #define testClass_h @interface testClass : NSObject @property NSString* _name; @property int32_t _age; //-(void)set_name:(NSString *)_name; // //-(void)set_age:(int32_t)_age; @end #endif
源文件如下:
#import <Foundation/Foundation.h> #import "testClass.h" @implementation testClass @end
成员类型
BOOL类型实际是一个unsigned char类型,包含YES和NO;
成员以@property修饰,默认自动生成setter和getter方法;
属性
可以理解为C++里的成员。使用@property关键字修饰。修饰词如下:
1. readonly、readwrite:默认readwrite。readonly标识该属性只读,外部不能修改其值;
2. 线程相关 atomic、nonatomic:默认nonatomic。但会消耗较多资源(有锁)。因此建议在不需要的场合设置为nonatomic;
3. strong、weak:默认strong。表示该属性对其相应的对象是强引用。weak表示弱引用,弱引用是不是可以理解为C++里的指针赋值给其他变量,其他变量能找到该指针所指向的对象,但不对该对象的释放负责??
4. 访问权限相关 copy、assign、retain:默认assign。assign一般用于非对象类型的属性;copy多用于字符串类型;retain多用于对象类型;
如果使用assign,则不添加任何内存管理方法(也就是直接将参数赋值给成员变量);如果使用retain,则相当于如下代码:
- (void) Setter : (NSString*) str { [str retain]; [var release]; val = str; }
对象创建
alloc是NSObject根类的方法,用来为对象动态分配内存;
+(id)alloc;
alloc返回值是一个id类型,它表示指向一个对象的指针。alloc还有一个重要任务,就是清理分配给对象属性的内存,将其置为0。也就是初始化对象的属性。
NSObject还提供了对象的初始化方法:
-(id)init;
这是一个实例方法。在init函数中你可以为对象的属性赋予合适的初值(??如何赋值??)
函数调用
有两种函数类型,一种是+号修饰,是类方法,一种是-号修饰,是实例方法。
- (void) setNum : (int) n : (int) d;
方法类型 返回类型 方法名称 有方法 参数1类型 参数1名称 参数2类型 参数2名称
构造函数和析构函数
构造函数分为两种,一种是带参数的,一种是不带参数的;可以自行实现init函数(即重写);重写带参数的构造函数需满足:
1. 返回值类型为intancetype;
2. 以init打头,以With开始;
- (instancetype)initWithName:(NSString*)name HP:(NSInteger)hp;
析构函数是dealloc,不可被显示调用(需调用release),可以用来调试该对象是否释放。可以重写:
- (void)dealloc
{
// 本地资源释放
[super dealloc];// 如果使用ARC则会报错,因为ARC模式下不允许调用父类的dealloc;
}
重写description函数
快速打印一个对象的所有信息,不能被显示调用。重写(NSString*)description;直接使用%@打印对象:NSLog(@"%@", xiaoMing);
ARC和MRC
ARC是automatic refrence counting(自动引用计数),Xcode工程创建后,一般在Build Setting内的设置都是ARC。MRC是mannual reference counting(手动引用计数)。
引用计数
OC在ARC下是不能获得引用计数的,需要首先在BuildSetting界面改为MRC后,调用[p retainCount]获得引用计数;
当调用[p retain]后,引用计数加一;
当调用[p release]后,引用计数减一;注意,过度调用release在Enable Zombie Objects选项下,会crash!!
自动释放池autoreleasepool
退出自动释放池时,会自动像池内的对象发送一条release消息。但是,自动释放池并不保证池内对象一定会被释放。我们都知道,对象是有引用计数的,也就是说,如果该对象的引用计数大于等于2,则该对象在退出自动释放池时,不会被释放。
比如ARC下的如下代码:
@autoreleasepool { Student *s = [[Student alloc] init]; }
相当于MRC下的:
NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init]; Student *s = [[Student alloc] init]; [pool drain];
类的访问权限
默认权限是protected:
@interface Persion : NSObject {
@protected // 默认权限
@public
@private // 私有的,只能被当前类访问
}
声明的成员变量无属性修饰时,默认为private。
成员变量的访问权限可以控制,但成员函数的权限都是public。如何限制成员函数的权限呢?可以在.h文件不声明,.m文件实现后使用即可。
动态类型和静态类型
运行时才确定的类型为动态类型,一般用id标识;但使用时比较危险,因为它不能在编译期差错,访问到类型没有的函数时会crash;
懒加载
- (NSString*)girlFriend { if(_girlFriend == nil) { _girlFriend = @"temp girlFriend"; } return _girlFriend; }
总结
1. 头文件.h,源文件.m,Object-C++源文件.mm;
2. Object-C中的nil相当于NULL;
3. Object-C中的YES和NO相当于true和false;
4. #import相当于#include,可以防止重复引用;
5. Object-C中所有的类都必须继承自NSObject;
6. Object-C仅支持单一父类继承,不支持多重继承;
7. Object-C中所有对象都是指针的形式;
8. Object-C中使用self代替this;
9. Object-C中使用id代替void*,注意id没有星号;
10. Object-C中类的调用形式是[aInstance method:argv];
11. Object-C支持反射机制,支持Dynamic Typing、Binding、Loading。