1.类和对象
1.1定义类
面向对象的程序设计中有两个重要概念:类(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
{
//方法体
}
说明:
- 类实现部分的类型必须和类借口部分的类名相同。用于表示这是同一个类的接口部分和实现部分。
- 类实现部分也可以在类名后使用 ":父类名" 来表示继承了某个父类,单一般没必要。
- 类实现部分也可声明自己的成员变量,但这些成员变量只能在当前类访问。
4.类实现部分必须为类声明部分的每个方法提供方法定义。
1.2对象的产生和使用
定义变量: 类名* 对象名
创建对象: [[类名 alloc] 初始化方法]
alloc是OC的关键字,负责为类分配内存空间,创建对象,调用初始化方法对该实例执行初始化。所有的对象都继承类NSObject ,所有的类都有一个默认的初始化方法:init
.
也可以使用new创建对象 [类名 new]
OC调用方法的语法为:[调用者 方法名:参数 行参标签:参数值 ...]
1.3 self
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;
}
1.4 id类型
任意类型的对象都可复制给id类型的变量
id p = [[FKWorf alloc] init];
[p info];
2.方法详解
OC中方法的所属性:
- 方法不能独立定义,只能定义在类中
- 从逻辑意义上看,方法要么属于该类本身(+),要么属于该类的一个对象(-)
- 永远不能独立执行方法,执行方法必须使用类或对象作为调用者
2.1 形参个数可变的方法
定义方法时,在最后一个形参后增加逗号和三点(,...),则表明该形参可以接受多个参数值。
长度可变的形参只能处于形参列表的最后,一个方法中最多只能包含一个长度可变的形参。
定义语法:-(void)test:(NSString*)name,...
获取形参:
- va_list,定义指向可变参数列表的指针
- va_start,函数,制定开始处理可变形参的列表,并让指针指向可变形参列表的第一个参数
- va_end,结束处理可变形参,释放指针变量
- va_arg,该函数范湖获取指针当前指向的参数的值,并将指针指向下一个参数
-(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);
}
}
3.成员变量
成员变量指的是在类接口部分或类实现部分定义的变量,OC的成员变量都是实例变量。
访问实例变量 实例->实例变量
声明实例变量,系统会为实例变量执行默认初始化,基本类型的实例变量默认被初始化为0,指针类型的成员变量默认被初始化nil
4.隐藏和封装
4.1封装
封装是指将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息 ,而是通过该类提供的方法类实现对内部信息的操作和访问。
4.2 访问控制符
4个访问控制符:@private
,@package
,@protected
,@public
4.3 @package 访问控制符
@package修饰的成员变量,可以在当前类和同一镜像的中访问,同一镜像是指,编译后生成的同一个框架或同一个执行文件
4.4合成存取方法
- 在类接口部分使用
@property
指令定义属性。使用@property
定义属性无需放在类接口的花括号里,直接放在@interface
、@end
之间。@property
指示符放在属性定义的最前面。 - 在类中实现的部分使用
@synthesize
指令声明该属性。
以上步骤会合成成对的setter和getter方法,还会自动在类实现部分定义一个与getter方法同门的成员变量。
使用@syethesize的语法格式 @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,被赋值的对象引用计数加1 -
strong
,weak
强引用、弱引用,强引用指向被赋值的对象,name对象就不会自动回收;弱引用指向的对象可能被回收 -
unsafe_unretained
与weak
相似,unsafe_unretained所引用的对象被回收后,unsafe_unretained指针不会被赋值为nil
,可能导致程序崩溃