黑马程序员——OC类的初始化与点语法

——- android培训java培训、期待与您交流! ———-

一、类的初始化方法

每个类都有构造方法,这里的初始化方法就是和构造方法一个概念的.
下面来看一下如何自定义初始化方法:
Person.h

#import <Foundation/Foundation.h>  

@interface Person : NSObject{  
    NSString *_name;  
    NSInteger _age;  
}  

//自定义初始化方法,必须以init开头  
- (id)initWithName:(NSString *)name withAge:(NSInteger)age;  

//打印信息  
- (void)showInfo;  

@end  

这里我们定义了一个初始化方法,对名称和年龄进行初始化赋值操作
注:OC中自定义初始化方法的名称必须是以initWith开头

在来看一下实现:
Person.m

#import "Person.h"  

@implementation Person  

- (instancetype)initWithName:(NSString *)name withAge:(NSInteger)age{  
    //固定写法,可以背下来哦~~  

    self = [super init];  //调用父类的初始化方法  

    if(self ){  
        _name = name;  
        _age = age;  
    }  

    return self;  
}  

- (void)test{  
    NSLog(@"test");  
}  

- (void)showInfo{  
    [self test];              //调用自己的方法  
    NSLog(@"name is %@ and age is %d",_name,_age);  
}  

@end  

这里我们看到了,初始化方法返回的类型是instancetype类型,关于OC中的instancetype类型,可以认为和C语言中的void*是相等的,这种类型在OC中经常被用到,还有就是self关键字的使用,这里的self关键字就相当于Java中的this关键字,指代当前类对象,还有super关键字,这个和Java中的super也是一样的,指代父类对象。还有一个是nil,他就相当于Java中的null,空对象的概念,用于判断的。
同时这里还要记住一点:
以后OC中自定义初始化的方法的模板:

//固定写法,可以背下来哦~~  
//调用父类的初始化方法 
- (instancetype)init{ 
self = [super init];  
if(self){  
    赋值语句;           //初始化变量  
}    
return self;  

这个就是一个模板,背下来吧,不过用多了,自然就记住了。

下面来看一下如何使用初始化方法:
main.m

#import <Foundation/Foundation.h>  

#import "Person.h"  

int main(int argc, const charchar * argv[]) {  
    @autoreleasepool {  
        Person *person = [[Person alloc] initWithName:@"xiaobai" withAge:22];  
        [person showInfo];     //调用showInfo方法

        person = [[Person alloc] init];  //初始化person
        [person showInfo];  

        //instancetype,类似于void*  
        //但是instancetype类型一般不这么使用,一般会作为方法的返回值 
        instancetype person1 = [[Person alloc] initWithName:@"huangdaoyang" withAge:23];  
        [person1 showInfo];  
    }  
    return 0;  
}  

我们使用了我们自定义的方法实例化了一个Person对象出来,同时调用他的showInfo方法,打印结果,这里我们也会发现Person的init方法任然可以使用。这个init方法是NSObject父类的,可以猜想到这个方法的逻辑功能就是初始化,所以我们在自定义初始化方法的时候,都是会用到这个方法的。当然我们可以定义多个初始化方法。

二、OC中的点语法

  • 点语法只能适用于set/get方法,如果没有对应的set/get方法的话,是不能使用.语法的;
  • OC中的get方法和Java中不太一样,OC中只要一个方法有返回值都可以认为是get方法.

下面来看一个例子吧:
Person.h

#import <Foundation/Foundation.h>  

@interface Person : NSObject{  
    //点语法只能适用于set/get方法,如果没有对应的set/get方法的话,是不能使用.语法的  
    //这里的get方法和其他语言不一样,只要有返回值就是get方法  
    NSString *_name;  
    NSInteger _age;  
}  

- (void)setName:(NSString *)name;  
- (void)setAge:(NSInteger)age;  

- (NSString *)name;  
- (NSInteger) age;  

//这里要注意,showInfo也是一个get方法  
- (NSString *)showInfo;  

//只定义,不实现,所以在调用[person test]的时候,编译时候不会报错  
//但是运行的时候就会报错了,因为编译的时候只会判断方法有没有定义,而运行的时候是需要判断这个方法有没有实现  
- (void)test;  

@end  

在{}中定义了两个属性,注意都是以下划线开头的。然后在给这两个属性定义get/set方法,这样我们就可以使用点语法来访问这两个属性了。
同时这里要注意的是其实showInfo方法也是一个get方法,因为他又一个返回值类型。
所以在OC中使用点语法有两个条件:

  • 必须是属性
  • 有对应的get/set方法

下面来看一下实现:
Person.m


#import "Person.h"  

/** 
 #import和#include的区别 
    1.当我们在代码中使用两次#include的时候会报错:因为#include相当于拷贝头文件中的声明内容,所以会报重复定义的错误 
      但是使用两次#import的话,不会报错,所以他可以解决重复导入的问题,他会做一次判断,如果已经导入一次就不导入了 
 */  

@implementation Person  

- (void)setName:(NSString *)name{  
    _name = name;  
    NSLog(@"setName is Execute");  
}  
- (void)setAge:(NSInteger)age{  
    //这里要注意,如果我们定义的全局变量是age而不是_age的话  
    //这里不能用age = age进行赋值  
    //但是也不能使用self.age = age,因为self.age等价于[self setAge:age]这样就会出现死循环了  
    //所以我们在定义全局变量的时候一般都会加上一个下划线以便区分  
    _age = age;  
    NSLog(@"setAge is Execute");  
}  
- (NSString *)name{  
    NSLog(@"getName is Execute");  
    return _name;  
}  
- (NSInteger) age{  
    NSLog(@"getAge is Execute");  
    return _age;  
}  
- (NSString *)showInfo{  
    NSLog(@"showInfo is Execute");  
    return _name;  
}  

@end  

这里对get/set方法的实现,看到上面的注释:
这里不能使用self.age = age,因为self.age等价于[self setAge:age],这样就会出现死循环了,原因很简单,因为OC中的点语法相当于调用set/get方法,那么在set/get方法中调用set/get方法,那就会出现了死循环了。所以这点一定要注意。
还有一个需要注意的是,刚刚在Person.h中定义了一个test方法,但是在Person.m中并没有实现,在OC中编译是不会报错的,但是运行的时候就会报错了。

看一下如何使用点语法:
main.m


#import <Foundation/Foundation.h>  
#import "Person.h"    
int main(int argc, const charchar * argv[]) {  
    @autoreleasepool {  
        Person *person = [[Person alloc] init];  
        //此处的点语法调用的是set方法,等价于[person setName:@"jiangwei"];  
        person.name = @"jiangwei";  
        person.age = 22;  
        //此处的点语法调用的get方法,等价于NSString *name = [person name];  
        NSString *name = person.name;  
        NSLog(@"name is %@",name);  

        name = person.showInfo;  
        NSLog(@"name is %@",name);  

        //调用test方法  
        [person test];  
    }  
    return 0;  
}  

这里就可以使用点语法进行赋值和取值操作了,其实等价于调用他们的get/set方法。

这里需要注意的是报了一个错误,这个错误也是我们经常犯的一个错误,就是这个方法没有实现,我们在Person.h中定义了test方法,但是没有在Person.m中进行实现,在main.m中进行调用就报了这个错误,但是编译的时候是没有报错的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值