一·类与对象
定义类:
面向对象的程序设计过程中有两个重要概念:类与对象,也是称为实例。其中类是某一批对象的抽象,可以把类理解成某种概念;对象是一个存在的实体。
定义类的步骤:

接口部分是对成员变量进行定义,而实现部分是对方法的精细化。
方法声明的语法:

类的实现语法

代码展示:
对象的产生与使用
- 定义变量
- 创建对象
- 接口与实现部分
#import <Foundation/Foundation.h>
//接口部分
@interface FKPerson : NSObject { //@interface是开始的标志
//下面定义了两个成员变量
NSString* _name;
int _age;
}
//下面定义了一个setName: andAge: 方法
- (void) setName :(NSString *) name andAge : (int) age;
//下面定义了一个say: 方法, 并不提供实现
- (void) say: (NSString *) content;
//下面定义了一个不带形参的info方法
- (NSString*) info;
//定义一个类方法
+ (void) foo;
@end //@end是结束的标志
//实现部分
@implementation FKPerson {
//定义一个只能在实现部分使用的成员变量 (被隐藏的成员变量)
int _testAttr;
}
//定义一个只能在实现部分使用的方法
- (void) test {
NSLog(@"--只能实现部分定义的test方法--");
}
//下面定义了一个setName: andAge: 方法
- (void) setName :(NSString *) n andAge: (int) a {
_name = n;
_age = a;
}
//下面定义了一个say: 方法, 并不提供实现
//"say:"有冒号的表示有形参的方法
- (void) say: (NSString *) content {
NSLog(@"%@", content);
}
//下面定义了一个不带形参的info方法
- (NSString*) info {
[self test];
return [NSString stringWithFormat:@"我是羽毛球选手,名字为:%@,年龄为%d。", _name, _age];
}
+ (void) foo {
NSLog(@"FKPerson类的类方法,通过类名调用");
}
@end
//对象的产生与实现
int main(int argc, const char * argv[]) {
@autoreleasepool {
FKPerson* person = [[FKPerson alloc] init];
//init初始化 alloc分配内存
[person say: @"hello i love iOS"];
[person setName:@"何斐" andAge: 19];
NSString* info = [person info];
NSLog(@"person -info 的信息为:%@",info);
[FKPerson foo];
}
return 0;
}
self关键字
OC提供了一个self关键词,关键词总是指向调用该方法的对象。
self关键词最大的作用是让类中的一个方法访问该类的另一方法或成员变量。
代码展示:
重要的批注都在代码中。
#import <Foundation/Foundation.h>
//首先是声明部分
@interface FKDog : NSObject
- (void) jump;
- (void) run;
@end
//再是实现部分
@implementation FKDog
- (void) jump {
NSLog (@"正在执行jump方法");
}
- (void) run {
//无self的时候,要新创建一个FKDog的对象
//FKDog* d = [[FKDog alloc] init];
//[d jump];
//self不能出现在类方法中;当出现在调用的方法中,它代表的对象不确定,只有被调用的时候才可以确定。
[self jump];
NSLog(@"正在执行run方法");
}
@end
//主函数部分
int main(int argc, const char * argv[]) {
@autoreleasepool {
FKDog* dog = [[FKDog alloc] init];
[dog jump];
[dog run];
}
return 0;
}
d关键词
id可以表示所有对象的类型,任意类的对象都可以复制给id类型变量。
当通过id类型的变量来调用方法时,oc就将会执行动态绑定,oc将会跟踪对象所属的类,并在运行时判断该对象所属的类,而不是在编译时确定要调用的方法。
//例如下面的示例代码:
#import <Foundation/Foundation.h>
@interface FKPerson : NSObject { //@interface是开始的标志
//下面定义了两个成员变量
NSString* _name;
int _age;
}
- (void) say: (NSString *) content;
@end
@implementation FKPerson
- (void) say : (NSString *) content {
NSLog(@"%@", content);
}
@end
int main (int argc , char * argv[] ) {
@autoreleasepool {
//定义id类型的变量,并将FKPerson对像赋值给该变量
id p = [[FKPerson alloc] init];
//使用p变量来调节say:方法
//程序将在运行时执行动态绑定。
[p say:@"疯狂iOS讲义"];
}
return 0;
}
形参个数可变的方法
在定义方法时,在最后一个形参名后增加逗号和三点(,…),则表明该形参可以接受多个参数值。下面是定义形参可变的方法。
为了在程序中获取个数可变的参数,需要使用如下关键字

#import <Foundation/Foundation.h>
@interface VarArgs : NSObject
//定义一个形参可变的方法
- (void) test: (NSString*) name, ...;
@end
@implementation VarArgs
- (void) test: (NSString* ) name, ... {
//使用va_list定义一个argList指针变量,该指针变量指向可变参数列表
va_list argList;
//如果第一个name参数存在,才需要处理后面的参数
if (name) {
//由于name参数并不在可变参数列表中,因此先处理name参数
NSLog(@"%@", name);
//让argList指向第一个可变参数列表的第一个参数,开始提取可变参数的列表
va_start(argList, name);
NSString* arg = va_arg(argList, id);
//va_arg用于提取argList指针当前指向的参数,并将参数指针移动到只想下一个参数
//arg变量用于保存当前获取的参数,如果该参数不为nil,进入循环体
while (arg) {
//打印每一个参数
NSLog(@"%@", arg);
//再次提取下一个参数,并将指针移动到指针指向下一个参数
arg = va_arg(argList, id);
}
//释放argList指针,结束提取
va_end(argList);
}
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
VarArgs* va = [[VarArgs alloc] init];
[va test:@"疯狂iOS讲义", "疯狂Android讲义", "疯狂Ajax讲义", nil];
}
return 0;
}
模拟类变量
OC并不支持类似于Java的类变量,为了模拟类变量,可以在类实现部分定义static修饰的全局变量,并提供一个类方法来暴露该全局变量。
FKUser的接口部分声明两个类方法分别用于修改或获取类变量,示例代码如下:
模拟类的变量
#import <Foundation/Foundation.h>
@interface FKUser : NSObject
+ (NSString* ) nation;
+ (void) setNation: (NSString* ) newNation;
@end
static NSString* nation = nil;
@implementation FKUser
+ (NSString* ) nation {
//返回nation全局变量
return nation;
}
+ (void) setNation:(NSString *)newNation {
//对nation全局变量赋值
if (![nation isEqualToString: newNation]) {
nation = newNation;
}
}
@end
int main (int argc , char * argv[] ) {
@autoreleasepool {
//为FKUser的类赋值
[FKUser setNation: @"陕西"];
//访问FKUser的类变量
NSLog(@"FKUser的nation类变量为: %@",[FKUser nation]);
}
return 0;
}
单例模式
如果一个类始终只能创建一个实例则这个类被称为单例类。
单例类通过static全局变量来实现,每次程序需要获取该实例时,程序首先判断该static全局变量是否为nil,则初始化一个实例并赋值给全局变量。
//代码如下
#import <Foundation/Foundation.h>
@interface FKSinglenton: NSObject
+ (id) instance;
@end
static id instance = nil;
@implementation FKSinglenton
+ (id) instance {
//如果instance为nil
if (!instance) {
//创建一个Singletion实例,并将该实例赋值给instance全局变量
instance = [[super alloc] init];
}
return instance;
}
@end
int main (int argc , char * argv[] ) {
@autoreleasepool {
//判断两次获取的实例是否相等,程序返回1,(代表真)。
NSLog(@"%d" ,[FKSinglenton instance] == [FKSinglenton instance]);
}
return 0;
}