面向对象的程序设计中有两个重要概念:类(class)和对象(object),类事某一批对象的抽象,对象是一个具体存在的实体。
Objective-C定义类需要氛围2个步骤
定义接口部分的语法:
@interface MyClass:NSObject
{
int count;
id data;
NSString* _name;
}
-(id)initWithString:(NSString)aName;
+(MyClass)createMyClassWithString:(NSString* aName);
@end
@interface用于声明定义类的接口部分,@end表明定义结束。其后紧跟该类d一对花括号用于声明该类的成员变量;花括号后面的部分用于声明该类的方法。定义类的接口声明部分防灾头文件中。
定义成员变量
类型 成员变量名;
声明方法:
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index
方法类型标识:+ 或者- ,+代表该方法是类方法,直接类型即可调用;-代表该方法是实例方法,必须对象才能调用。
返回值类型:可以是OC允许的任何数据类型。
方法签名关键字:由方法名,行参标签和冒号组成。OC建议为后面的每个行参都指定一个行参标签,该行参标签可以很好的说明该行参的作用。
Objective-C的方法声明中,所有的类型(包括void)都应该使用圆括号括起来。
定义实现部分的语法:
@implementation MyClass { int _count; id _data; NSString* _name; } -(id)initWithString:(NSString*)aName { //方法体 } +(MyClass*)createMyClassWithString:(NSString*)aName { //方法体 }
说明:
定义变量: 类名* 对象名
创建对象: [[类名 alloc] 初始化方法]
alloc是OC的关键字,负责为类分配内存空间,创建对象,调用初始化方法对该实例执行初始化。所有的对象都继承类NSObject ,所有的类都有一个默认的初始化方法:init
.
也可以使用new创建对象 [类名 new]
OC调用方法的语法为:[调用者 方法名:参数 行参标签:参数值 ...]
self关键字总是指向调用该方法的对象。self关键字最大的作用是让类中的一个方法访问该类中另一个方法或者成员变量。
#import <Foundation/Foundation.h>
@interface FKWorf:NSObject
{
NSString* _name;
}
-(void) setName:(NSString*)_name;
-(void) info;
@end
@implementation FKWorf
-(void) setName:(NSString*) n
{
self->_name = n;
}
-(void) info
{
NSLog(@"我是%@",self->_name);
}
@end
int main(int argc, char const *argv[])
{
@autoreleasepool
{
FKWorf* worf = [[FKWorf alloc] init];
[worf info];
}
return 0;
}
任意类型的对象都可复制给id类型的变量
id p = [[FKWorf alloc] init];
[p info];
OC中方法的所属性:
定义方法时,在最后一个形参后增加逗号和三点(,...),则表明该形参可以接受多个参数值。
长度可变的形参只能处于形参列表的最后,一个方法中最多只能包含一个长度可变的形参。
定义语法:-(void)test:(NSString*)name,...
获取形参:
-(void)test:(NSString*)name,...
{
va_list argList;
//如果第一个name参数存在,才需要处理后面的参数
if(name)
{
NSLog(@"%@",name);
va_start(argList,name);
NSString* arg = va_arg(argList,id);
while(arg)
{
NSLog(@"%@",arg);
arg = va_arg(argList,id);
}
va_end(argList);
}
}
成员变量指的是在类接口部分或类实现部分定义的变量,OC的成员变量都是实例变量。
访问实例变量 实例->实例变量
声明实例变量,系统会为实例变量执行默认初始化,基本类型的实例变量默认被初始化为0,指针类型的成员变量默认被初始化nil
封装是指将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息 ,而是通过该类提供的方法类实现对内部信息的操作和访问。
4个访问控制符:@PRivate
,@package
,@protected
,@public
@package修饰的成员变量,可以在当前类和同一镜像的中访问,同一镜像是指,编译后生成的同一个框架或同一个执行文件
@property
指令定义属性。使用@property
定义属性无需放在类接口的花括号里,直接放在@interface
、@end
之间。@property
指示符放在属性定义的最前面。@synthesize
指令声明该属性。以上步骤会合成成对的setter和getter方法,还会自动在类实现部分定义一个与getter方法同门的成员变量。
@sythesize property名[=成员变量名]
#import <Foundation/Foundation.h>
@interface FKUser:NSObject
@property (nonatomic) NSString* name;
@property NSString* pass;
@property NSDate* birth;
//-(void)setName:(NSString*) name;
@end
@implementation FKUser
@synthesize name=_name;
@synthesize pass;
@synthesize birth;
-(void)setName:(NSString*) name
{
self->_name=[NSString stringWithFormat:@"+++%@",name];
}
@end
int main(int argc, char const *argv[])
{
FKUser* user=[[FKUser alloc] init];
[user setName:@"唐僧"];
[user setPass:@"1234"];
[user setBirth:[NSDate date]];
NSLog(@"name=%@,pass=%@,birth=%@",[user name],[user pass],[user birth]);
return 0;
}
@property
和类型间用括号的额外指示符
assign
指定对属性只是简单赋值,不更改对所赋的值的引用计数。用于NSinteger及short float double 结构体等C数据类型atomic
(nonatomic
) 默认atomic,指定合成的方法是否为原子操作,当一个线程进入存取方法的方法体后,其他线程无法进入该存、去方法,避免多线程冰法破坏对象的完整性。copy
使用copy,当调用setter方法对成员变量赋值时,会将被赋值的对象复制一个副本,再讲该副本赋值给成员变量。getter
、setter
用于为合成的getter、setter方法指定自定义方法名@property (assign,nonatomic,getter=wawa,setter=nana:) int price;
readonly
,readwrite
(默认) ,readonly 指示系统只合成getter方法retain
属性赋值时,原来所引用的对象的引用计数器减1,被赋值的对象引用计数加1strong
,weak
强引用、弱引用,强引用指向被赋值的对象,name对象就不会自动回收;弱引用指向的对象可能被回收unsafe_unretained
与weak
相似,unsafe_unretained所引用的对象被回收后,unsafe_unretained指针不会被赋值为nil
,可能导致程序崩溃