Objective-C 【@property和@synthesize关键字】
———————————————————————————————————————————
@property关键字的使用及注意事项
直接上代码和注释了!
//
//@property关键字的使用
//①使用格式: @property 数据类型 方法名(去掉set后的)
// 作用:在Xcode4.4之前,用于帮我们实现get/set方法的声明(只是实现了声明部分,实现部分自己写);在Xcode4.4之后,有增强功能。
//②就一个注意事项,要说的是在使用@property关键字的时候,后面的方法名一定要正确,那么不正确会怎样呢?
//举个例子:
//下面 @property int age; 这句话,如果写成 @property int _age; 我们来测试一下。
//在下面的测试中,我们发现,只在方法名前面加了一个下划线,但是我们为此所做的调整非常的多。我们很清楚,一改全改。在Person.m文件中我们发生了这样的改动:
//-(void)set_age:(int)_age
//{
// NSLog(@"这是age的set方法!");
// self->_age=_age;
//}
//-(int)_age
//{
// NSLog(@"这是age的get方法!");
// return self->_age;
//}
//我们可以清楚的看到,我们set方法名发生的变化,然后传入的参数名也发生了变化(和实例变量名同名了),由于同名,我们还用了self关键字,在get方法中也是利用了self关键字进行返回值
//所以说,我们最好不要改变@property后面的方法名,否则会带来不必要的麻烦
//代码正文:
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
NSString *_name;
int _age;
}
@property NSString * name;
//-(void)setName:(NSString *)name;
//-(NSString *)name;
//@property int age;//先注释掉,然后将age换成_age
@property int _age;//首先,肯定会出错,然后我们应该怎么改呢?我们要知道,这时的方法名已经变成了 _age 了。
//-(void)setAge:(int)age;
//-(int)age;
@end
@implementation Person
-(void)setName:(NSString *)name
{
// NSLog(@"这是name的set方法!");
_name=name;
}
-(NSString *)name
{
// NSLog(@"这是name的get方法!");
return _name;
}
-(void)set_age:(int)_age
{
NSLog(@"这是age的set方法!");
self->_age=_age;
}
-(int)_age
{
NSLog(@"这是age的get方法!");
return self->_age;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Person *p=[Person new];
// p.name=@"wang";
// p.age=20;
// NSLog(@"name = %@,age = %d",p.name,p.age);
Person *p1=[Person new];
p1._age=18;//[3819:437482] 这是age的set方法!
NSLog(@"p1._age= %d",p1._age);//[3819:437482] 这是age的get方法![3819:437482] p1._age= 18
}
return 0;
}
———————————————————————————————————————————
@synthesize关键字的使用及注意事项
/*
代码格式: @synthesize 方法名 (应该和@property 后面跟的一致)
注意:
要先在@interface ... @end中定义这个变量,然后用@property写他的set、get方法的声明,最后再在@implementation ... @end中写@synthesize 实现set、get方法。所以说,要想用@synthesize实现set、get方法,上面的两条(1.声明变量 2.使用@property关键字)缺一不可!!!(搭配使用)
*/
上代码:
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
NSString *_name;
int _age;
}
//这里声明了两个成员变量的set和get方法
@property NSString * name;
@property int age;
-(void)test;//用来检测当前的实例对象值,此时的结果是 [4031:471936] _name=(null),_age=0
//为什么呢?那么我们来看一下刚刚我们的实现是怎么写的!
//-(void)test
//{
// NSLog(@"_name=%@,_age=%d",_name,_age);//这里显然用了_name来输出当前的实例对象的值,但是这里是不对的。我们刚才提到了,@synthesize在使用的时候事先为我们创建了一个新的变量name,所以说,当前的值应该输出当前的name,而不是_name。
//}
@end
@implementation Person
//@synthesize作用:帮我们实现了 实例变量的get和set方法
//下面我们将下面的@synthesize关键字展开,看看里面到底是怎么实现的。
@synthesize name;//我们只展开name这个成员变量的get和set方法实现,@synthesize name;句话展开之后为:
//首先我们明白一点,@synthesize为我们新创建了一个变量name
//-(void)setName:(NSString *)name
//{
// self->name=name;//这里为什么不是 _name=name; 那就是因为@synthesize为我们新创建了一个变量name
//}
//-(NSString *)name
//{
// return name;
//}
@synthesize age;
-(void)test
{
NSLog(@"_name=%@,_age=%d",_name,_age);
NSLog(@"name=%@,age=%d",name,age);
NSLog(@"self->name=%@,self->age=%d",self->name,self->age);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p=[Person new];
p.name=@"wang";
p.age=21;
NSLog(@"\n_name:%@\n_age:%d",p.name,p.age);
[p test];
// 我们最后在test方法内部测试了这三种写法的结果,最后结果如下:
// _name=(null),_age=0
// name=wang,age=21
// self->name=wang,self->age=21
// 显然,name、age和self->name、self->age指的都是使用@synthesize关键字时创建的新变量,他们的值都不是空值
}
return 0;
}
———————————————————————————————————————————
@synthesize的 批量操作 和 指定实例变量的值操作
上代码:
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
NSString *_name;
int _age;
int _weight;
int _height;
}
@property NSString* name;
@property int age,weight,height;
-(void)test;
@end
@implementation Person
@synthesize name=_name;
@synthesize age=_age,weight=_weight,height=_abc;
-(void)test
{
// NSLog(@"\n_name=%@\n_age=%d\n_weight=%d\n_height=%d",name,age,weight,height);
// 上面这句话就是错误的了,系统不识别这些实例变量名(name、age、weight、height),错误为:Use of undeclared identifier 'name'; did you mean '_name'?(这里有四个变量,我只在这里写了一个变量的提示错误,其实错误有四个),我们并没有用@synthesize自动为我们设置的实例变量。实质上,当指定实例变量名以后,再不会操作默认的实例变量了。
// 当然,我们可以将上面的其中一个变量做一些小调整,比如 height=_abc;
NSLog(@"\n_name=%@\n_age=%d\n_weight=%d\n_height=%d\n_abc=%d",_name,_age,_weight,_height,_abc);
// 显然这里_abc是有数值的,而_height系统是不认识的,因为我们用 @synthesize height=_abc; 操作的是_abc这个实例变量名,而不是_height了
// 所以说,一句话, @synthesize 方法名 = 实例变量名; 我们实现的是方法,而方法处理什么实例变量是我们自己定义的或者是默认的。
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Person *p=[Person new];
// p.name=@"wang";
// p.age=21;
// p.weight=190;
// p.height=181;
//
// NSLog(@"\nname=%@\nage=%d\nweight=%d\nheight=%d",p.name,p.age,p.weight,p.height);
// 这句话正常输出。说明了当多个实例变量(成员变量)的数据类型一致的时候,我们可以:
// ① @property int age,weight,height; //批量声明set、get方法
// ② @synthesize age,weight,height; //批量实现set、get方法
// 这里要着重说明一点,@property只能是相同类型的实例对象才能批量声明,但是@synthesize可以不同类型的实例对象一起批量实现
// 接下来是这一部分的一个重点。我们之前知道,在调用关键字@synthesize的时候,我们知道@synthesize会为我们创建一个新的变量进行操作,而这句话 @synthesize 方法名; 其实这里系统是操作默认的实例变量。那么我们能不能利用这个方法去操作指定的实例变量呢?答案当然是肯定的。
// 代码格式: @synthesize 方法名 = 实例变量名;
// 这样,我们就能利用这个方法去操作我们需要操作的实例变量了,例如下面的几行代码,下面的代码是通过设置指定的实例变量名来操作实现get、set方法的
// 我们是这样指定的:
// @synthesize name=_name;
// @synthesize age=_age,weight=_weight,height=_height;
Person *p1=[Person new];
p1.name=@"lao";
p1.age=21;
p1.weight=90;
p1.height=164;
// NSLog(@"\n_name=%@\n_age=%d\n_weight=%d\n_height=%d",p1.name,p1.age,p1.weight,p1.height);
// 当然直接输出的话,还是应该用调用get方法的方式输出,但是不同之处是,如果我们用一个新的test方法来输出这几个实例变量的名的话,就不太一样了
[p1 test];
// 结果如下:
// _name=lao
// _age=21
// _weight=90
// _height=0
// _abc=164
}
return 0;
}
———————————————————————————————————————————
@property增强使用
在Xcode 4.4之后的版本,我们写实例变量的set、get方法时,可以只写@property 而不写@synthesize。比如说有两个声明了的实例变量(属性成员变量) _name和_age,我们只使用@property关键字的话,那么我们相当于同时声明和实现了_name和_age的set、get方法。(这里是对带有下划线的实例变量名进行操作的,这也是苹果的定义)。而且他的增强还有一点,如果我们在@interface...@end中根本就不声明实例变量的话,那么也可以!只使用@property可以帮我们声明带有下划线的实例变量!(★★★比如说,我写了
@property int age; 那么系统自动声明了一个_age的实例变量,而不用去写 int _age; 但是要知道的是,这里自动声明的实例对象是私有的,无法被子类 继承 和 访问!!!想要被子类继承,那么还必须在@interface … @end中的大括号内声明这些实例对象!!!★★★)
上代码:
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property NSString * name;
@property int age;
-(void)test;
@end
@implementation Person
-(void)test
{
NSLog(@"_name=%@,_age=%d",_name,_age);
// NSLog(@"name=%@,age=%d",name,age); 显然这句话是错误的,在增强@property中,是只认带有下划线的实例变量的。
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p=[Person new];
p.name=@"wang";
p.age=21;
[p test];
}
return 0;
}
———————————————————————————————————————————
@property增强使用的一个补充——子类继承问题
上代码:
#import <Foundation/Foundation.h>
@interface Person : NSObject
//{
// NSString *_name;
// int _age;
//}
//加上这几句声明属性,那么子类就能继承了,但是还是无法访问
@property NSString * name;
@property int age;
-(void)test;
@end
@implementation Person
-(void)test
{
NSLog(@"_name=%@,_age=%d",_name,_age);
// NSLog(@"_name=%@,_age=%d",self->_name,self->_age); 这句话是和上面一样的
// NSLog(@"name=%@,age=%d",name,age); 显然这句话是错误的,在增强@property中,是只认带有下划线的实例变量的。
}
@end
@interface Student : Person
-(void)test1;
@end
@implementation Student
-(void)test1
{
// NSLog(@"\n_name=%@\n_age=%d",_name,_age);
// 由于_name和_age这两个实例对象没有声明,只是用@property关键字创建出来的,所以说是相对私有的变量,无法被子类继承和访问,所以上面的这句话是出错的,显示并没有_name和_age的声明。
// 如果想让这句话正确,那么只需要在@interface ... @end中的大括号里声明即可(但是这样只能做到被继承,但是还是不能被访问,如果访问,需要写@synthesize)
// NSLog(@"\n_a=%d",_a);
// 在这里我们将_a定义为Person类的@private类型的变量,显示_a只能继承但是不能访问,这里的私有和上面_name/_age的私有还有有一些区别的
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Person *p=[Person new];
// p.name=@"wang";
// p.age=21;
//
// [p test];
Student *s=[Student new];
s.name=@"lao";
s.age=21;
[s test];
// 这里可能有人会问,为什么我们创建的Student类的实例对象怎么还能调用其父类的set、get方法
// 那是因为我们将 @property NSString * name; 和 @property int age; 写在了interface里,这是暴露的属性,自然能访问
}
return 0;
}
———————————————————————————————————————————
@property 增强下重写set、get方法
我们如果使用@property增强去定义变量属性(这里成为方法也可以),那么会出现一些情况,比如过我调用set方法传进来的值不对怎么办?我想稍微改一下set、get方法怎么办。这就需要重写set、get方法。
重写时有亮点需要注意:
①set、get方法只能重写其中的一个,如果两个都重写,编译器会报错的
②重写其中一个(set或者get),那么另外一个编译器会自动生成,且重写过的编译器就不会生成默认的了
———————————————————————————————————————————
版权声明:本文为博主原创文章,未经博主允许不得转载。
Objective-C 【@property和@synthesize关键字】的更多相关文章
- iOS 详细解释@property和@synthesize关键字
/** 注意:由@property声明的属性 在类方法中通过下划线是获取不到的 必须是通过 对象名.属性 才能获取到!- @property和@synthesize关键字是针对成员变量以及get/se ...
- Objective-C 点语法 成员变量的作用域 @property和@synthesize关键字 id类型
点语法 1.利用点语法替换set方法和get方法 方法调用 Student *stu = [Student new]; [stu setAge : 18]; int age = [stu age]; ...
- Objective-C--@property,@synthesize关键字介绍
Objective-C–@property,@synthesize关键字介绍 转载:http://www.cnblogs.com/QM80/p/3576282.html /** 注意:由@proper ...
- ios中点语法、property跟synthesize用法
一:OC中得点语法 1> 点语法的基本使用: ·使用 对象.成员变量 可以实现设置成员变量值,和获取成员变量的值 2> 点语法的本质 (点语法是Xcode编译器自己帮我们完成的一个 ...
- OC开发系列-@property和@synthesize
property和synthesize 创建一个Person类.提供成员属性的_age和_height的setter和getter方法. #import <Foundation/Foundati ...
- OC基础--关键字@property 和 @synthesize
一.@property关键字需要掌握的知识: 1.用在@interface中,用来自动生成setter和getter的声明 例:@property int age;--相当于执行了右边的代码--> ...
- OC中两个关键字的作用:@property和@synthesize
两个关键字的使用:@property和@synthesize 一.@property关键字这个关键字是OC中能够快速的定义一个属性的方式,而且他可以设置一些值,就可以达到一定的效果,比如引用计数的问题 ...
- OC的特有语法-分类Category、 类的本质、description方法、SEL、NSLog输出增强、点语法、变量作用域、@property @synthesize关键字、Id、OC语言构造方法
一. 分类-Category 1. 基本用途:Category 分类是OC特有的语言,依赖于类. ➢ 如何在不改变原来类模型的前提下,给类扩充一些方法?有2种方式 ● 继承 ● 分类(Categor ...
- Objective-C中的@property和@synthesize用法
@代表“Objective-C”的标志,证明您正在使用Objective-C语言 Objective-C语言关键词,@property与@synthesize配对使用. 功能:让编译好器自动编写一个与 ...
随机推荐
- 在Android项目中使用AndroidAnnotations(配置框架,显示Hello World!)
使用这个框架可以极大的简化在开发Android过程中的代码.提高开发的效率.这里简单说一下配置方式.和使用办法. 项目的地址为:AndroidAnnotations Jar包下载地址:3.0.1 下载 ...
- 【M22】考虑以操作符复合形式(op=)取代其独身形式(op)
1.对于内置类型,x = x+y 与x+=y的结果相同. 2. x=x+y 与 x+=y的结果相同,但二者做的事情差别很大. a.x=x+y做的事情:方法内有个局部对象,值为x+y,返回局部对象,返回 ...
- iOS开发——UI_swift篇&UItableView实现移动单元格
UItableView实现移动单元格 1,下面的样例是给表格UITableView添加单元格移动功能: (1)给表格添加长按功能,长按后表格进入编辑状态 (2)在编辑状态下,可以看到单元格后面出现 ...
- iOS开发——实用篇Swift篇&项目开发常用实用技术
项目开发常用实用技术 实现拨打电话 要实现打电话功能,最简单最直接的方式便是:直接跳到拨号界面 (注意:这个需要真机调试,模拟器无效果) UIApplication.sharedApplica ...
- 实例源码--Android理财工具源码
下载源码 技术要点: 1.Sqlite数据库的综合使用 2.控件的综合使用 3. 源码带详细的中文注释 ...... 详细介绍: 1. Sqlite数据库的综合使用 本套源码采用了Sqlite ...
- PHP.2-LAMP平台介绍及网站的工作原理
LAMP平台介绍及网站的工作原理 1.HTTP协议 URL(UniformResourceLocator)统一资源定位符,就是网页地址的意思.[格式:协议://主机.端口.文件.附加资源] ##URL ...
- 小白日记25:kali渗透测试之提权(五)--利用配置不当提权
利用配置不当提权 与漏洞提权相比,更常见的方法.在大部分企业环境下,会有相应的补丁更新策略,因此难以通过相应漏洞进行入侵.当入侵一台服务器后,无法照当相应的补丁进行提权,可通过寻找是否存在配置不当进行 ...
- ArcGIS动态文本
处理动态文本 来自:http://resources.arcgis.com/zh-cn/help/main/10.2/index.html#/na/00s900000013000000/ Deskto ...
- (重刷)HDU 1874 畅通工程续 + HDU 2544 最短路 最短路水题,dijkstra解法。
floyd解法 今天初看dijkstra,先拿这两题练手,其他变形题还是不是很懂. 模版题,纯练打字... HDU 1874: #include <cstdio> #define MAXN ...
- [Android]应用的前后台运行
在开发中,你是不是没有抽象一个出常用的类,那你可能要为你的懒惰付出很大的代价.要时刻记得自己的工具箱,不断往里面添加一些小小玩意.今天就给大家带来一个很有意思的例子.前后台运行!! 在Android开 ...