https://www.gravatar.com/avatar/7a0c24f697ea1587001c36d00039b60f?s=240&d=mp

Objective-C语法学习-static关键字

在变量声明前加上关键字static,可以使局部变量保留多次调用一个方法所得的值。如下:

[objc] static int hitCount = 0; [/objc]

声明整数hitCount是一个静态变量。和其他常量局部变量不同,静态变量的初始值为0,所以前面显示的初始化是多余的。此外,他们只在程序开始执行时初始化一次,并且在多次调用方法时保存这些数值。

所以编码序列

[objc] -(void)showPage { static int pageCount = 0; …. ++pageCount; …. } [/objc]

可能出现在一个showPage方法中,它用于记录该方法的调用次数。只在程序开始时局部静态变量设置为0,并且在连续调用showPage方法时获得新值。

注意,将pageCount设置为局部静态变量和实例变量之间的区别。对于前一种情况,pageCount能记录调用showPage方法的所有对象打印页面的数目。对于后一种情况,pageCount变量可以计算每个对象的页面数目,因为每个对象都有自己的pageCount副本。

记住只能在定义静态和局部变量的方法中访问这些变量。所以,即使静态变量pageCount,也只能在showPage函数中访问。可以将变量的声明移到所有方法声明的外部(通常放在implementation文件的开始处),这样所有方法都可以访问它们,如:

[objc] #import "Printer.h"

static int pageCount;

@implementation Printer

@end [/objc]

这样,该文件中包含的所有实例或者类方法都可以访问变量pageCount。

Objective-C语法学习-使用点运算符访问属性

Objective-C语言允许你使用非常简便的语法访问属性。要获得myFraction中存储的numerator的值,可使用下面的语句:

[objc] Fraction* myFraction = [[Fraction alloc] init]; [myFraction numerator]; [/objc]

这会像myFraction对象发送numerator消息,从而返回所需的值。从Objective-C 2.0开始,现在可以使用点运算符编写以下等价的表达式:

[objc] myFraction.numerator [/objc]

一般格式为:

[objc] instance.property [/objc]

还可以使用类似的语法进行赋值:

[objc] instance.property = value [/objc]

这等价于编写以下表达式:

[objc] [instance setProperty:value] [/objc]

使用下面的代码将分数的numerator和denominator设置为1/3: [objc] [myFraction setNumerator:1];

[myFraction setDenominator:3]; [/objc]

下面是两行等价的代码: [objc] myFraction.numerator = 1;

myFraction.denominator = 3; [/objc]

Objective-C语法学习-具有多个参数的方法

Objective-C如何实现多参数输入呢?

先复习一下objc怎么传递参数,例如:

[objc] //声明部分 -(void)setNumerator:(int)n;

//测试部分 [myFraction setNumerator:1]; [/objc]

通过方法名后面跟上冒号,表示接受的参数。

带参数名的方法

如果要实现多个参数传递呢?我们可以通过下面的方式实现:

[objc] [instance setX:(int)x andY:(int)y]; [/objc]

这种感觉。

我们看一个具体的例子:

接口文件:Fraction.h

[objc] #import Foundation/Foundation.h

@interface Fraction:NSObject

@property int numerator,denominator; -(void)print; -(void)setTo:(int)n over:(int)d; -(double)convertToNum;

@end [/objc]

然后,在实现文件中添加新方法定义。

实现文件:Fraction.m

[objc] #import "Fraction.h"

@implementation Fraction @synthesize numerator,denominator; -(void)print { NSLog(@"%i/%i",numerator,denominator); } -(double)convertToNum { if(denominator!=0) return (double)numerator/denominator; else return 1.0; } -(void)setTo:(int)n over:(int)d { numerator = n; denominator = d; } @end [/objc]

setTo: over:方法接受两个整型参数,n和d,并把他们赋值给该分数对应的域numerator和denominator。

Objective-C语法学习-合成存取器方法@property

在objc中,可以自动生成设置函数方法和获取函数方法(统称为存取器方法)。

第一步是在接口部分中使用@property指令标识属性。这些属性通常是实例变量。在Fraction类中,两个实例变量numerator和denominator都属于此类属性。例如:

[objc]@interface Fraction:NSObject { int numerator; int denominator; } @property int numerator,denominator; -(void)print; -(double)convertToNum; @end [/objc]

注意,我们没有包括下列设置函数方法和获取函数方法的定义:numerator、denominator、setNumerator和setDenominator。我们要让objc-2.0编译器为我们自动生成或合成这些方法。如何完成呢?只需在实现部分中使用@synthesize指令即可,如下:

[objc] #import "Fraction.h" @implementation Fraction @synthesize numerator,denominator; -(void)print { NSLog(@"%i/%i",numerator,denominator); } -(double)convertToNum { if(denominator != 0) return (double)numerator/denominator; else return 1.0; } @end [/objc]

下面这行内容告诉objective-c编译器,为两个实例变量(numerator和denominator)的每一个生成一对设置函数方法和获取函数方法:

[objc]@synthesize numerator,denominator;[/objc]

通常,如果有称为X的实例变量,那么在实现部分包括以下行会导致编译器自动实现一个获取函数方法X和一个设置函数方法setX:

[objc]@synthesize x[/objc]

即使此处看起来并非什么大事,但是让编译器完成这项工作是值得的,因为生成的存取器方法是高效的,并且在使用多个核心的多台机器上,使用多线程时也可正常运行。

Objective-C语法学习-对象传递

我们知道了Objective-C中传递参数的方式,但是如果我们需要把一个实例对象作为参数传递时该如何做呢?

假设我们有一个Fraction类,现在我们有一个方法需要接受它自己的实例对象,那么我们可以这样做:

[objc] -(void)add:(Fraction*)f; [/objc]

注意参数f的声明:

[objc] (Fraction*)f [/objc]

这句语句说明add:方法的参数类型是Fraction类。星号是必须的,所以声明

[objc] (Fraction)f [/objc]

是不正确的。

使用方法如下: [objc] Fraction* aFraction = [[Fraction alloc] init]; Fraction* bFraction = [[Fraction alloc] init];

[aFraction add:bFraction]; [/objc]

Objective-C语法学习-继承

一切从根类开始

[objc] @interface Fraction:NSObject … @end [/objc]

NSObject是所有类的根类,Fraction由NSObject派生而来。类Fraction称为子或者子类(subclass)。所有未明确继承父类的类都默认继承NSObject。

从术语角度而言,可以将一个类称作子类和父类。相似地,还可以将类称作子类和超类。

只要定义一个新类(不是一个新的根类),该类都会继承一些属性。例如,很明显父类的所有实例变量和方法都成为新类定义的一部分。这意味着子类可以直接访问这些方法和实例变量,就像直接在类定义中定义了这些子类一样。

下面是一个名为ClassA的对象的声明,它有一个方法initVar:

[objc] @interface CalssA:NSObject { int x; } -(void)initVar; @end [/objc]

initVar方法简单地把100赋值给ClassA的实例变量:

[objc] @implementation ClassA -(void)initVar { x = 100; } @end [/objc]

现在,再定义一个名为ClassB的类:

[objc] @interface ClassB:ClassA -(void)printVar; @end [/objc]

声明的第一行

[objc] @interface ClassB:ClassA [/objc]

说明ClassB并非NSObject的子类,而是ClassA的子类。所以,尽管ClassA的父类(或超类)是NSObject,但是ClassB的父类却是ClassA。

因此,ClassA是NSObject的子类,而ClassB是ClassA的子类,也是NSObject的子类(从学术上讲,它是子类的子类或孙类)。同样,NSObject是ClassA的超类,也是ClassB的超类。

下面是ClassB的完整声明,ClassB定义了一个名为printVar的方法:

[objc] @interface ClassB:ClassA -(void)printVar; @end

@implementation ClassB -(void)printVar { NSLog(@"x=%i",x); } @end [/objc]

虽然在ClassB中没有定义任何实例变量,但是可以通过printVar方法输出实例变量x的值。这是由于ClassB是ClassA的子类,因此它继承ClassA的所有实例变量。

测试代码:

[objc] int main(int argc,char* argv[]) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; ClassB* b = [[ClassB alloc] init]; [b initVar]; [b printVar]; [b release]; [pool drain]; return 0; } [/objc]