点语法
1.set方法和get方法的调用
OC中的set方法和get方法都是对成员变量的修改和操作。在方法调用上set方法和get方法都使用中括号来调用,如果仅仅是修改成员变量的值可以直接使用OC的点语法的功能来简化set方法和get方法的调用进而简化重复代码书写。
Person.h
@interface Person : NSObject
{
int _age;
NSString *_name;
}
- (void)setAge:(int)age;
- (int)age;
- (void)setName:(NSString *)name;
- (NSString *)name;
@end
Person.m
@implementation Person
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
- (void)setName:(NSString *)name;
{
_name = name;
}
- (NSString *)name
{
return _name;
}
@end
main.m
int main()
{
Person *p = [Person new];
p.age = 10;
NSLog("age = %d",p.age);
p.name = @"seed";
NSLog("name = %@",p.name);
return 0;
}
运行结果:
2014-06-04 22:19:48.374 ff[527:303] age = 10
2014-06-04 22:19:48.377 ff[527:303] name = seed
Program ended with exit code: 0
使用点语法修改成员变量就是调用set方法和get方法,点语言调用更直观地体现成员变量的修改。
2.property声明简化
property的作用就是可以自动声明操作成员变量的set方法和get方法。property同时也自动生成方法的实现,使得set方法和get方法的书写量大为减少。
Student.h
@interface Student : NSObject
@property int age;
@property int score;
@end
Student.m
@implementation Student
@end
main.m
int main()
{
Student *s = [Student new];
s.age = 10;
NSLog(@"age = %d",s.age);
s.score = 100;
NSLog(@"score = %d",s.score);
return 0;
}
运行结果:
2014-06-04 22:31:31.281 ff[560:303] age = 10
2014-06-04 22:31:31.283 ff[560:303] score = 100
Program ended with exit code: 0
直接使用property不仅可以直接声明方法完成方法实现,也间接地实现了成员变量地内部定义。虽然在Student没有直接定义成员变量,但是property在方法实现中自动声明了带下划线地成员变量。
Student.h
@interface Student : NSObject
@property int age;
@property int score;
- (void)test;
@end
Student.m
@implementation Student
- (void)test
{
_age = 20;
_score = 90;
}
@end
main.m
int main()
{
Student *s = [Student new];
s.age = 10;
NSLog(@"age = %d",s.age);
s.score = 100;
NSLog(@"score = %d",s.score);
[s test];
NSLog(@"age = %d",s.age);
NSLog(@"score = %d",s.score);
return 0;
}
运行结果:
2014-06-04 22:36:09.619 ff[571:303] age = 10
2014-06-04 22:36:09.622 ff[571:303] score = 100
2014-06-04 22:36:09.623 ff[571:303] age = 20
2014-06-04 22:36:09.624 ff[571:303] score = 90
Program ended with exit code: 0
自动生成的成员变量是私有的,不能直接被外部访问只能在类的内部访问。
3.synthesize的实现
synthesize与property相对,property自动声明方法,synthesize自动完成方法的对应实现。一般synthesize可以省略不写,也可以写明成员变量的赋值保护成员变量不被非法访问。
Good.h
@interface Good : NSObject
{
int _cou;
NSString *_na;
}
@property int count;
@property NSString *name;
@end
Good.m
@implementation Good
@synthesize count = _cou;
@synthesize name = _na;
@end
main.m
int main()
{
Good *g = [Good new];
g.count = 10;
NSLog(@"count = %d",g.count);
g.name = @"buster";
NSLog(@"name = %@",g.name);
return 0;
}
运行结果:
2014-06-04 23:10:36.334 cc[658:303] count = 10
2014-06-04 23:10:36.338 cc[658:303] name = buster
Program ended with exit code: 0
synthesize可以指定成员变量间的赋值,这样可以保护成员变量被非法访问。
构造方法
1.id类型
id就是OC里面的万能指针,各种类型都能指向。定义一个id类型的变量就是定义了一个指向实例对象的一个指针。这个指针可以代替实例变量调用本身的方法。
Apple类
Apple.h
#import <Foundation/Foundation.h>
@interface Apple : NSObject
@property int num;
@property int size;
- (void)test1;
- (int)appleSize;
@end
Apple.m
#import "Apple.h"
@implementation Apple
- (void)test1
{
NSLog(@"apple");
}
- (int)appleSize
{
return _size;
}
@end
Plum类
Plum.h
#import <Foundation/Foundation.h>
@interface Plum : NSObject
@property int num;
@property int size;
- (void)test2;
- (int)plumSize;
@end
Plum.m
#import "Plum.h"
@implementation Plum
- (void)test2
{
NSLog(@"plum");
}
- (int)plumSize
{
return _size;
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Apple.h"
#import "Plum.h"
int main()
{
Apple *a = [Apple new];
a.num = 5;
NSLog(@"num = %d",a.num);
Plum *p = [Plum new];
p.num = 8;
NSLog(@"num = %d",p.num);
id data = a;
[data test1];
int size = [data appleSize];
NSLog(@"size = %d",[data appleSize]);
data = p;
[data test2];
size = [data plumSize];
NSLog(@"size = %d",size);
return 0;
}
运行结果:
2014-06-04 23:59:10.820 fru[749:303] num = 5
2014-06-04 23:59:10.823 fru[749:303] num = 8
2014-06-04 23:59:10.825 fru[749:303] apple
2014-06-04 23:59:10.826 fru[749:303] size = 0
2014-06-04 23:59:10.827 fru[749:303] plum
2014-06-04 23:59:10.827 fru[749]
定义一个id类型指针之后,id类型的指针变量赋值之后,就可以间接地调用接收类的方法。因为id自身带有*号,所以定义id类型变量时不用加*定义。
2.init方法
init方法是OC里面对实例化对象进行初始化的方法,这个方法来自于所有类的源头NSObject类。init方法可以直接使用,也可以在子类中覆写,自定义成自己需要的方法。
phone.h
@interface Phone : NSObject
{
int color;
int num;
}
- (void)print;
@end
phone.m
@implementation Phone
- (id)init
{
if(self = [super init])
{
num = 10;
}
return self;
}
- (void)print
{
NSLog(@"num = %d",num);
}
main.m
int main(int argc, const char * argv[])
{
Phone *p = [[Phone alloc] init];
[p print];
return 0;
}
运行结果:
2014-06-05 10:21:55.987 vv[511:303] num = 10
Program ended with exit code: 0
程序运行完成之后,num成员变量的值初始化成了10。这说明init方法覆写了父类中的init方法。覆写初始化方法也可以不用声明init方法,因为继承NSObject类就已经有了init方法。覆写init方法时,要调用父类中的init方法。
3.自定义构造方法
init方法也可以自己设计定义成自定义构造方法。自定义 构造方法可以自带参数,写成带参数组成的方法。
Phone.h
@interface Phone : NSObject
@property int color;
@property int num;
@property NSString *name;
- (id)initWithName:(NSString *)name;
- (id)initWithNum:(int)num;
- (id)initWithName:(NSString *)name andinitWithNum:(int)num;
@end
Phone.m
@implementation Phone
- (id)initWithName:(NSString *)name
{
if(self = [super init])
{
_name = name;
}
return self;
}
- (id)initWithNum:(int)num
{
if(self = [super init])
{
_num = num;
}
return self;
}
- (id)initWithName:(NSString *)name andinitWithNum:(int)num
{
if(self = [super init])
{
_num = num;
_name = name;
}
return self;
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Phone.h"
int main(int argc, const char * argv[])
{
Phone *p = [[Phone alloc] initWithName:@"lsmseed"];
Phone *p1 = [[Phone alloc] initWithNum:10];
Phone *p2 = [[Phone alloc] initWithName:@"seed" andinitWithNum: 20];
NSLog(@"num = %d name = %@",p.num,p.name);
NSLog(@"num = %d name = %@",p1.num,p1.name);
NSLog(@"num = %d name = %@",p2.num,p2.name);
return 0;
}
运行结果:
2014-06-05 10:43:08.215 vv[575:303] num = 0 name = lsmseed
2014-06-05 10:43:08.218 vv[575:303] num = 10 name = (null)
2014-06-05 10:43:08.220 vv[575:303] num = 20 name = seed
Program ended with exit code: 0
自定义构造方法可以自由选定传入的参数和类型,这样可以方便灵活地对已经实例化的类进行相应地初始化。使用自定义构造方法时也不能忘了使用父类中的init方法。
Class类对象
1.class的使用
class就是类类型,说起来奇怪它也是一种类型,就是类本身也是一种类型。OC中我们写的类也可以当作对象来看,即类对象。实例化后的对象可以调用class方法来获取对应的类对象。
Phone.h
@interface Phone : NSObject
@property NSString *name;
- (id)initWithName:(NSString *)name;
@end
Phone.m
@implementation Phone
- (id)initWithName:(NSString *)name
{
if(self = [super init])
{
_name = name;
}
return self;
}
@end
main.m
int main(int argc, const char * argv[])
{
Phone *p = [[Phone alloc] init];
Class pc = [p class];
Phone *p1 = [[pc alloc] initWithName:@"seed"];
NSLog(@"object = %@",pc);
NSLog(@"pcname = %@",p1.name);
return 0;
}
运行结果:
2014-06-05 11:07:14.324 vv[665:303] object = Phone
2014-06-05 11:07:14.328 vv[665:303] pcname = seed
Program ended with exit code: 0
class对象打印出的结果是对应的类名。同时class对象也可以调用对应类的对象方法来初始化对象。
2.load方法和initialize方法
load方法就是加载要使用的类,而且类的load方法只调用一次。initialize方法是在类第一次调用时加载,因此initialize方法可以测试出类第一次调用的位置。
Person.h
@interface Person : NSObject
@property int num;
@property NSString *name;
@end
Person.m
@implementation Person
+ (void)load
{
NSLog(@"Person is loading");
}
+ (void)initialize
{
NSLog(@"Person initialize");
}
@end
Car.h
@interface Car : NSObject
@property int num;
@property int color;
@end
Car.m
@implementation Car
+ (void)load
{
NSLog(@"Car is loading");
}
+ (void)initialize
{
NSLog(@"Car initialize");
}
@end
main.m
int main(int argc, const char * argv[])
{
Car *c = [[Car alloc] init];
NSLog(@"num = %d",c.num);
Person *p = [[Person alloc] init];
p.name = @"lsm";
return 0;
}
运行结果:
2014-06-05 11:19:34.793 ccc[730:303] Car is loading
2014-06-05 11:19:34.799 ccc[730:303] Person is loading
2014-06-05 11:19:34.808 ccc[730:303] Car initialize
2014-06-05 11:19:34.809 ccc[730:303] num = 0
2014-06-05 11:19:34.809 ccc[730:303] Person initialize
Program ended with exit code: 0
因为程序中有两个类,所以load方法都加载了。由于Car类先调用了方法,所以Car先调用了initialize方法。Person在Car之后定义并使用,因此,Person后调用initialize方法。
3.decription方法
decription方法就是对类内容的一个显示,默认情况用NSLog用%@显示的是类名+对象地址。decription的返回值就是NSLog在屏幕上输出的内容。
Decrit.h
@interface Decrit : NSObject
@property int age;
@property NSString *name;
@end
Decrit.m
@implementation Decrit
- (NSString *)description
{
return [NSString stringWithFormat:@"seed age is %d",_age];
}
+ (NSString *)description
{
return @"seed";
}
@end
main.m
int main(int argc, const char * argv[])
{
Decrit *d = [[Decrit alloc] init];
NSLog(@"d = %@",d);
Class dd = [Decrit class];
NSLog(@"class dd is %@",dd);
return 0;
}
运行结果:
2014-06-05 12:09:30.759 dd[896:303] d = seed age is 0
2014-06-05 12:09:30.763 dd[896:303] class dd is seed
Program ended with exit code: 0
默认创建对象时,调用对象方法description方法。如果是用class类型打印,就是调用的类description方法。两者调用的都是description方法,但是两者的调用者和调用的方式不同。
SEL方法
1.sel的封装定义
sel是OC的一种数据类型的封装。对象是通过sel间接地调用方法。sel数据是调用对象方法的一个桥梁。
Person.h
@interface Person : NSObject
@property int age;
@property NSString *name;
- (void)test1;
@end
Person.m
@implementation Person
- (void)test1
{
NSLog(@"test is run");
}
@end
main.m
int main(int argc, const char * argv[])
{
Person *p = [[Person alloc] init];
p.name = @"lsmseed";
p.age = 10;
SEL n = NSSelectorFromString(@"name");
SEL s = @selector(test1);
NSLog(@"name is %@",[p performSelector:n]);
[p performSelector:s];
return 0;
}
运行结果:
2014-06-05 12:39:03.677 sse[988:303] name is lsmseed
2014-06-05 12:39:03.680 sse[988:303] test is run
Program ended with exit code: 0
sel类型的数据存储的是对象方法的对应地址,使用sel可以通过对应的地址调用对象中的方法。每个类中的方法都有对应的sel数据。
2.sel方法的调用
sel类型的数据被封装好了之后,一般使用performSelector来调用对应的方法。通过sel获得对应方法的地址后,间接调用方法。
Person.h
@interface Person : NSObject
@property NSString *name;
- (void)test2:(NSString *)name;
@end
Person.m
@implementation Person
- (void)test2:(NSString *)name
{
NSString *str = NSStringFromSelector(_cmd);
NSLog(@"name = %@",name);
NSLog(@"selector = %@",str);
}
@end
main.m
int main(int argc, const char * argv[])
{
Person *p = [[Person alloc] init];
[p performSelector:@selector(test2:) withObject:@"seed"];
return 0;
}
运行结果:
2014-06-05 13:13:15.167 sse[1032:303] name = seed
2014-06-05 13:13:15.171 sse[1032:303] selector = test2:
Program ended with exit code: 0
sel可以直接调用方法,也可以带参数传入方法中使用。sel是方法调用的另一种体现,可以在只知道方法名而不知道调用方式的时候,间接地调用方法。
----------------------ASP.Net+Unity开发、.Net培训、期待与您交流!----------------------