黑马程序员_OC的特有语法

---------------------- ASP.Net+Unity开发 .Net培训 、期待与您交流!----------------------

点语法

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培训、期待与您交流!----------------------



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值