OC_04属性的声明、实现,便利及设置器和访问器

我们先将工程搭建好,建立以下几个类,都继承于NSObject
这里写图片描述
我的person.h建立有误,最好将p大写。
将所有相关头文件导入到main.m函数中
1.OC中的方法
方法:类的功能代码,在(.h)文件中声明,在(.m)文件中实现
语法:
+|-(返回类型)方法名:参数列表
{
//方法体
}
减号(-)表示实例方法,加号(+)表示类方法
//类方法
注意:
1.类方法可以调用类方法;
2.类方法不可以调用实例方法,但是类方法可以通过创建对象来访问实例方法;
3.类方法不可以使用实例变量,类方法可以使用self,因为self不是实例变量;
4.类方法作为消息,可以被发送到类里面去,不能发送到对象里面去(实际上,就是可以通过类但是不能通过对象调用类方法的意思)

我们在Person.h中,简略写一下相关函数

@public
    NSString *_name;
    NSInteger _age;
    NSString *_hobby;
-(void)sayHello; //实例方法
-(void)sayHelloName:(NSString *)name
                        Age:(NSInteger)age
                       Hobby:(NSString *)hobby;     //实例方法
+(void)sayHi;
+(void)hiGuys; 

到Person.m文件中实现一下

@implementation person
-(void)sayHello{
    NSLog(@"sayhello");
}
-(void)sayHelloName:(NSString *)name Age:(NSInteger)age Hobby:(NSString *)hobby{
    NSLog(@"HELLO GUYS!My name is %@,I am %ld years old,I like %@!",name,age,hobby);
}
+(void)sayHi{
    NSLog(@"sayhi!");
}
+(void)hiGuys{
    //1.类方法可以调用类方法
    //self是什么?self 代表当前对象的指针
    [self sayHi];
//2.类方法不可以使用实例方法... ...
person *personk =[person new];
[personk sayHello];
//3.类方法不可以使用实例变量.......   
}

2.我相信大家看到了上面函数中的某些方法的使用,下面就来介绍一下我们的设置器和访问器,以及我们的便利初始化函数和便利构造器

◎设置器和访问器
//设置器与访问器
/*在Student.h中举个栗子~

NSString *_name;
    NSInteger _age;
    NSString *_hobby;
-(void)setName:(NSString *)name;//        name设置器
-(NSString *)name;//name访问器

-(NSInteger)age;//age访问器
-(void)setAge:(NSInteger)age;//age设置器

-(void)setHobby:(NSString  *)hobby;//           hobby设置器
-(NSString *)hobby;//hobby访问器

//设置器和访问器的作用:
/*
1.隐藏了实例变量
2.控制实例变量的读写
3.做正确性校验

设置器(setter)和访问器(getter)的命名规则:
1.设置器: -(void)set首字母大写的实例变量:(实例变量的返回值类型)去掉下划线的实例变量名
2.访问器: -(实例变量的返回值类型)去掉下划线的实例变量名

note:
对于类的名称,其手写字母大写
对于变量,首写字母小写
并且都遵循驼峰命名规则

setter和getter的好处:
1.在setter中可以加入合法性检查,比如设置颜色的函数中,对于RGB颜色要判断其值在0~255之间。
2.更新与被设置变量相关的其它变量的值,比如在一个潜水艇模拟系统中,改变了其水下深度时,要相应的更新所受压强。
3.在debug时,可以在其中,尤其是在setter中加入追踪log;
4.在多线程环境中,如果要保护对象的并发访问,则必须在getter/setter中加入同步锁

缺点:手动编写麻烦
*/
我们去Student.m中实现一下

-(void)setName:(NSString *)name{
    _name = name;
}
-(NSString *)name{
    return _name;
}
//对age属性来说,做正确性校验
-(void)setAge:(NSInteger)age{
    if(age < 18){
        _age = 18;
    }
    else{
        _age = age;
    }
}
-(NSInteger)age{
    return _age;
}
//正确性校验
-(void)setHobby:(NSString *)hobby{
    _hobby = hobby;
    if ([_hobby isEqualToString:@"Listening Music"]) {
        _hobby = @"is Comfortable";
    }
    else{
        _hobby = @"is Uncomfortable";
    }
}
-(NSString *)hobby{
    return _hobby;
}

◎便利初始化函数和便利构造器
/*
便利初始化函数
注意命名规范:init开头

便利构造器
便利构造器只不过是把对象分配内存和调用便利初始化函数初始化对象的代码封装起来,让用户使用起来更加方便
*/
3.我们来看看 属性的声明
@property NSString *address;
//相当于声明了设置器 和 访问器
/*
访问读写 , 原子性 ,内存管理

1、存取方法名称
系统默认的存取方法名称是propertyName和setPropertyName,就如我们Student类的name,其对应的存取方法名称是name 和 setName,这样做是为了方便我们采用点语法。
getter = getterName
setter = setterName
注意,如果改变了getter 和 setter 方法名称 ,则必须提供自定义的方法。
2、访问读写
readwrite: 指明属性是可读写的,这是默认值,因此可以省略。
readonly : 指明属性是只读的,系统只会产生getter(访问器)方法,而不会产生setter方法
对于只读属性,如果试图通过点语法赋值,会编译错误

3、原子性
atomic:原子操作 ,这是默认的。
nonatomic:非原子操作,会简单的操作属性值。这会加快属性值存取的速度,但是没办法保证在多线程环境下不出错

4、内存管理
retain 会通过retain来持有目标对象,之前的对象会接收到释放的消息
copy 会通过copy复制对象,之前的对象会接收到释放的消息
assign 采用简单的赋值方法,这是默认的方法
strong 表示强引用关系 ,即拥有目标对象的所有权
weak 表示弱引用关系 ,不拥有目标对象的所有权。当目标对象被销毁之后,属性值会被自动设为nil
strong 相当于 retain 或者 copy ,对象要用retain,copy,strong 来描述
weak 近似看做 assign 基本数据类型 要用到 assign

我们在NewStudent中举个小栗子~

@property  (readwrite ,nonatomic,strong)NSString *name;// *name----对象
@property (nonatomic,assign)NSInteger age;// age----基本数据类型
//-(void)setName:(NSString *)name;
//-(NSString *)name;
//-(void)setAddress:(NSString *)address;
//-(NSString *)address;
//-(void)setAge:(NSInteger )age;
//-(NSInteger)age;
-(id)initWithName:(NSString *)name
Age:(NSInteger )age Address:(NSString *)address;
+(id)newStudentWithName:(NSString *)name Age:(NSInteger)age Address:(NSString *)address;

到NewStudent.m文件中实现一下
//-(void)setName:(NSString *)name{
//    _name = name;
//}
//-(void)setAddress:(NSString *)address{
//    _address = address;
//}
//相当于设置器 和 访问器 的实现 也叫 属性的实现
//@synthesize address = _address;
//@synthesize name = _name;
//@synthesize age = _age;
/*
 注意:如果我们 将 @synthesize 注释掉, 这个时候 系统就会为我们产生下划线的开头的变量。
 _address 来代替 address
 */
//-(void)setAge:(NSInteger)age{
//    _age = age;
//}
//-(NSString *)name
//{
//    return _name;
//}
//-(NSString *)address{
//    return _address;
//}
//-(NSInteger)age
//{
//    return _age;
//}
-(void)setName:(NSString *)name{
        if ( [@"Jason" isEqualToString:name]) {
        _name = name;
    }
}
-(id)initWithName:(NSString *)name Age:(NSInteger)age Address:(NSString *)address{
    if (self = [super init]) {
//        _name = name;
        self.name = name;
        _age = age;
//        _address = address;
        self.address = address;
    }
    return self;
}
+(id)newStudentWithName:(NSString *)name Age:(NSInteger)age Address:(NSString *)address{
    NewStudent *newstudent = [[NewStudent alloc]initWithName:name Age:age Address:address];
    return newstudent;
}

4.大家从上面的函数发现,我用了self,id,及会用到的super这几个函数,那么,他们分别是什么意思呢?

id: 返回的类型是id数据类型,它是动态数据类型,可以指向任何类的对象,而不关心其具体类型,在运行时检查其具体类型,可以对其发送任何(存在的)消息。
self:指当前对象的指针。
super:指向父类对象的指针,子类使用super发送消息的时候,实际上就是告诉子类调用父类的方法,如果父类没有定义该方法,则继续在继承链上查找,直到寻找到位置,如果找到NSObject的位置还未找到,就会报错。

然后,我们将Teacher.h和Teacher.m也简要写一下吧~
.h 接口文件

 NSString *_name;
 NSInteger _age;
-(void)sayWord;
+(id)teacherWithName:(NSString *)name
                 Age:(NSInteger)age;
-(id)initWithName:(NSString *)name
              Age:(NSInteger)age;
-(void)classBegin;
.m实现文件
-(void)sayWord{
    NSLog(@"name = %@,age = %ld",_name,_age); 
}
-(void)classBegin{
    NSLog(@"%@老师,我有问题",_name);
}
+(id)teacherWithName:(NSString *)name Age:(NSInteger)age{
    Teacher *teacher = [[Teacher alloc]initWithName:name Age:age];
    return teacher;
}
-(id)initWithName:(NSString *)name Age:(NSInteger)age{
    if (self = [super init]) {
        _name = name;
        _age = age;
    }
    return self;
}
-(id)init{
    if (self = [super init]) {
        _name = @"Barry";
        _age = 14;
    }
    return self;
}

我们到main.m函数中调用一下

person *personl= [person new];
        personl->_name= @"Barry";
        personl->_age = 10;
        personl->_hobby = @"music";
        [personl  sayHello];
        [personl sayHelloName:@"Barry" Age:22 Hobby:@"music"];
        [person sayHi];
        Student *stu = [Student new];
        [stu setName:@"Rose"];
        [stu setAge:14];
        [stu setHobby:@"Listening Music"];
        NSString *name = [stu name];
        NSInteger age = [stu age];
        NSString *hobby = [stu hobby];

        NSLog(@"name = %@,age = %ld,hobby %@",name,age,hobby);
  //便利初始化函数 以及 便利构造器
        Teacher *teacher = [[Teacher alloc]init];
        [teacher sayWord];
        [teacher classBegin];
        Teacher *otherteacher1 = [[Teacher alloc]initWithName:@"Bob" Age:33];
        Teacher *otherteacher2 = [[Teacher alloc]initWithName:@"Baby" Age:20];
        [otherteacher1 sayWord];
        [otherteacher2 sayWord];
        [otherteacher1 classBegin];
        [otherteacher2 classBegin];
        //便利构造器使用
        Teacher *otherteacher = [[Teacher alloc]initWithName:@"Eason" Age:42 ];
        [otherteacher sayWord];

//属性的实现
        NewStudent *newStudent = [[NewStudent alloc] init];
        newStudent.name = @"Jason";
        newStudent.age = 22;
        newStudent.address = @"广东省CZ市XQ区CZ大道";
          NSLog(@"%@,%ld岁,住在%@",newStudent.name,newStudent.age,newStudent.address);

最后我们来看一下运行结果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值