Objective C 总结(三):对象
- 对象发送和接收消息
[someObject doSomething];
- 用指针跟踪对象
值类型:NSInteger,int,float,double,char,BOOL,变量直接存储了它的值
- (void)myMethod { int someInteger = 42;
NSString *name = @"Bob"; } @property float height;
@property (copy) NSString *firstName;
作为方法内的局部变量(上例中的someInteger),它分配到stack上,生存周期就是方法的周期对象类型:除基本类型以外的类型,它的数据是由基本类型组合构成的,对象是分配到heap上的,指針变量存储了它的地址值来引用对象
作为方法内的局部变量(上例中的name),它的生存周期像其它对象一样,是由引用计数来控制的,最后由运行时负责回收内存 - 传递对象
- (void)saySomething:(NSString *)greeting;
调用方法
NSString *str = @"Bob"; [someObject saySomething: str]
- 方法返回值
定义- (NSString *)uppercaseString;
调用
NSString *testString = @"Hello, world!"; NSString *revisedString = [testString uppercaseString];
- 给对象自身发送消息
@implementation XYZPerson - (void)sayHello { [self saySomething:@"Hello, world!"]; } - (void)saySomething:(NSString *)greeting { NSLog(@"%@", greeting); } @end
运行时会为每个实例方法传递当前对象的引用,在方法内用self关键字来表示。
- 对象在自身方法内调用父类的方法
@implementation XYZShoutingPerson - (void)saySomething:(NSString *)greeting { NSString *uppercaseGreeting = [greeting uppercaseString]; [super saySomething:uppercaseGreeting]; } @end
实例方法内用super关键字表示父类对象
- 对象都是动态创建的
对象的创建过程分二个阶段,一为对象分配内存,二为对象进行初始化,这样一个对象就创建了。
NSObject作为根类,提供了一些基本的功能
// 分配内存
+ (id)alloc;
// 初始化对象 - (id)init;NSObject *newObject = [[NSObject alloc] init];
这样对象newObject就创建了,对象的引用计数初始为1,newObject变量是跟踪对象的指针。id类型是范型对象指针,它可以引用任意NSObject类型。
初始化方法与其它方法没区别,是对alloc后返回的对象发送的一个消息,它也可以有参数- (id)initWithBool:(BOOL)value; - (id)initWithFloat:(float)value; - (id)initWithInt:(int)value; - (id)initWithLong:(long)value;
NSNumber *magicNumber = [[NSNumber alloc] initWithInt:42];
- (id)initWithInt:(int)value { self=[super init]; if(self) { self.number = value; } return (self); }
指定初始化方法必需要先初始化父对象,这样的语法,init方法可以是父类的其它初始化方法
if(self=[super init]) {
还可以定义工厂方法来创建对象+ (NSNumber *)numberWithBool:(BOOL)value; + (NSNumber *)numberWithFloat:(float)value; + (NSNumber *)numberWithInt:(int)value; + (NSNumber *)numberWithLong:(long)value;
Objective-C中大量应用了这样的工厂方法
也可以使用new 关键字来创建对象,它是调用了init初始化方法XYZObject *object = [XYZObject new]; // 这两种方式是一样的 XYZObject *object = [[XYZObject alloc] init];
NSString创建对象的简洁语法
NSString *someString = @"Hello, World!";
@“”就是创建NSString对象的简洁语法
用C语方的字符数组初始化NSStringNSString *someString = [NSString stringWithUTF8String:"Hello, World!"]; // 两种方式一样 NSString *someString = [NSString stringWithCString:"Hello, World!" encoding:NSUTF8StringEncoding];
NSNumber作为基本类型(int,long,float,double,BOOL,char)的对象包装类,(局部的基本类型直接存储了其值并分配到stack上的,要把它们像对象一样分配到堆上,需要进行对象的包装,NSNumber就是包装的类)也一样提供了简洁的语法
NSNumber *myBOOL = @YES; NSNumber *myFloat = @3.14f; NSNumber *myInt = @42; NSNumber *myLong = @42L;
NSNumber *myInt = @(84 / 2);
- Objective-C是动态语言
id类型是范型对象指针,可以引用任意的对象
id someObject = @"Hello, World!"; [someObject removeAllObjects];
上面示例中someObject引用了一个NSString实例,但是编译器不知道它实际是哪种类型对象(在示例中它是id类型),
removeAllObjects
消息可能在一些类中定义了(如NSMutableArray),编译上面的代码编译器不会提示任何错误,即便在运行是发生了异常(因为NSString没有定义这个方法),(这就是动态了)
重写上面的代码NSString *someObject = @"Hello, World!"; [someObject removeAllObjects];
编译上面的代码,编译器就会提示发生了错误,因为这时someObject具有了具体的类型NSString,而它没有定义发送的消息。
因为对象的类是在运行时决定的,XYZPerson *firstPerson = [[XYZPerson alloc] init]; XYZPerson *secondPerson = [[XYZShoutingPerson alloc] init]; [firstPerson sayHello]; [secondPerson sayHello];
示例的firstPerson和secondPerson引用了不同类型的对象,它们会在运行时调用各自实现的方法sayHello.
- 对象的比较
值类型的比较是 ==if (someInteger == 42) { // someInteger has the value 42 }
它比较了实际的值
对象,==则是用于比较两端是不是指向了同一个对象,它实际比较了地址的值if (firstPerson == secondPerson) { // firstPerson is the same object as secondPerson }
如果想要比较对象的数据是不是一样的,则要使用实现的方法NSObject的重载isEqual
if ([firstPerson isEqual:secondPerson]) { // firstPerson is identical to secondPerson }
- nil
值类型必须在使用之前进行初始化
BOOL success = NO; int magicNumber = 42;
但是对象指针就不用,编译器自动把它设置为nil
XYZPerson *somePerson; // ssomePerson == nil
判断指针是不是nil
if (somePerson != nil) { // somePerson points to an object }
if (somePerson) { // somePerson points to an object }
两种语法一样的效果。如果是nil,它的值会是0(false),如果引用了对象,它的值就不是0(true)
判断是nilif (somePerson == nil) { // somePerson does not point to an object }
if (!somePerson) { // somePerson does not point to an object }