Objective-C中的属性(property)

Objective-C中的属性(property)

  • 它组合了新的预编译指令和新的属性访问的语法,新的属性功能显著减少了必须编写的冗长代码的数量。

下面我们来比较下面的代码


//第一种声明方法
-(void)setRainHandling:(float) rainHanding;

-(float) rainHandling;

-(void)setSnowHandling:(float) snowHandling;

-(float) snowHandling;

//第二种声明方法
@property float rainHandling;

@property float snowHandling;

以上两段代码的作用是完全一样的,由此我们可以得出属性的作用是:

  • @property预编译指令的作用是自动声明属性的setter和getter方法,事实上,属性的名称不必与实例变量的名称相同,但大多数情况下它们是一样的。

我们知道了函数的settter和getter方法的声明,但是如何实现呢?我们接着看


//第一种实现方法
-(void)setRainHandling:(float) rh
{
rainHandling =rh;
}

-(float) rainHandling
{
return rainHandling;
}

-(void)setSnowHandling:(float) sh
{
snowHandling =sh;
}

-(float) snowHandling
{
return snowHandling;
}
//第二种实现方法
@synthesize rainHandling;

@synthesize snowHandling;

我们的目的是彻底的删除setter和getter方法,用以上的两行代码就可以完全代替。

对于synthesize这种编译器的功能有以下几点需要说明:

  • @sythesize它表示“创建了该属性的访问代码”。当遇到@sythesize
    rainHandling;这行代码时,编译器将添加实现 -setRainHandling:和-rainHandling方法的预编译代码。

  • Cocoa的访问器编写实用工具和其他平台上的UI生成器可以生成源代码,这些源代码随后会被编译。但是@sythesize预编译指令不同于代码生成。你永远也不会看到实现-setRainHandling:和-ranHandling的代码,这些方法确实存在并可以调用。

  • 在X-code 4.5以后的版本中,可以不必使用@sythesize了。

  • 所有的属性都是基于变量的,所以在你合成setter和getter方法的时候,编译器会自动创建与属性名称相同的实例变量。如果你没有声明这些变量,编译器也会声明的。如果我们不去自己实现@sythesize,编译器会给我们生成一个下滑线(_)开头的实例变量。如在头文件的定义中写@property
    (copy) NSString name; 在其实现中会有一个_
    name的实例变量。

点表达式的妙用

  1. Objective-C 2.0的属性引用了一些新的语法特性,使我们更加容易访问对象的属性,也就是点表达式。

  2. 如果点表达式出现了等号(=)的左边,该变量名称的setter方法将被调用。如果点表达式出现在了对象变量的右边,则该变量的getter方法将被调用。

  3. 点表达式只是调用访问方法的一种便捷方式,并没有什么神秘之处。

属性的扩展

  • assign //简单赋值,主要用于基本数据类型

  • copy //创建一个新的对象,新的对象和旧对象是独立的两个对象

  • retain //将对象计数器加1

  • readonly //表示只读属性  只会生成getter方法 不会生成setter方法

  • readwrite //默认值,表求生成setter和getter方法

  • nonatomic //非原子访问,不加同步 ,多线程并发访问提高性能
    (对多线程的保护,防止在未写完,被另一个线程读取,造成数据错误)

名称的使用

  一种非常普遍的情况是属性的名称与支持属性的实例变量名称相同,不过,有时候你可能希望实例变量是一个名称,而公开的属性是另一个名称。


//头文件的定义
#import "Tire.h"
//关于适应所有天气的Tire类的声明与定义

@interface AllWeatherTire : Tire
{
NSString *tireName;
}

@property float rainHanding;
@property float snowHanding;
//用于给我们我的轮胎起一个名字
@property (copy)NSString *name;

//实现
#import "AllWeatherTire.h"
@implementation AllWeatherTire
@synthesize name = tireName;

- (NSString*)description
{
NSString *desc;

desc = [NSString stringWithFormat:@"AllWeatherTier:name is %@,%.1f,%.1f, %.1f, %.1f",

self.name,self.pressure,self.treadDepth,self.rainHanding,self.snowHanding];

return desc;
}

 
  在这里编译器仍创建-setName:和-name方法,但在其实现代码中用的却是tireName实例变量。不过这样做的话,编译的时候将会遇到一些错误。因为我们直接访问的实例变量已经被修改了。我们可以选择用搜索并替换的name的方式来解决,也可以将实例变量的直接调用改成用访问的方法。比如在init方法中把
name [email protected]“Car” 改成self.name [email protected]"Car".

自己动手有时更好

  • 我们之前提到过属性是基于变量的,并且编译器会为你创建setter和getter方法。但是如果你不想要变量、setter和getter方法的话应该怎么办?

  • 答案是使用@dynamic关键字。

  • 如果你声明了dynamic属性,并且企图调用不存在的getter和setter方法,你将会得到一个错误。


@property(readonly) float bodyMassIndex;

@dynamic bodyMassIndex;

-(float)bodyMassIndex

{

/// ;
}
//如果调用不存在的setter和getter方法会报错。

属性的缺点

  属性不是万能的,如果方法并不适合属性所胡涵盖的较小范围的话。属性只支持替代
-setBlah和-blah方法,但是不支持那些需要接收额外参数的方法。例如:car对象中tire对象的代码。

-(void)setTire:(Tire *)tire atIndex:(int)index;

-(Tire *)tireAtIndex:(int)index;

属性的总结

  本文主要介绍了属性。在为对象变量执行常见的操作时,利用属性可以减少需要编写以及随后需要阅读的代码数量。使用@propert预编译指令可以告诉编译器:“嘿,这个对象具有这些类型的特性”
你还可以让属性传递其他信息,比如可变性(只读或者读写)。编译器在后台会自动生成对象变量的setter和getter方法。

  使用@sythesize预编译指令可以通知编译器生成访问的方法。你还可以控制由编译器生成的访问方法对哪些实例变量起作用。如果不想使用默认的行为,你完全可以编写自己的访问方法。你还可以使用@dynamic指令告诉编译器不要生成变量和代码。

  尽管点表达式通常出现在有属性的代码中,但是它只是调用对象的setter和getter方法的一种便捷方式。点表达式法减少了需要键入的字符数量,而且进一步方便了曾经使用其他语言的编程人员。

Objective-C中的属性(property),布布扣,bubuko.com

时间: 2024-10-01 04:40:03

Objective-C中的属性(property)的相关文章

【整理】Object-C中的属性(Property)的Setter:assign,copy,retain,weak,strong之间的区别和联系

iOS编程过程中,经常看到一些属性前面有些修饰符,比如copy,retain等. 这些关键字,是Object-C语言中,对于Property的setter. Mac官网: The Objective-C Programming Language – Declared Properties – Setter Semantics 中的解释是: Setter Semantics These attributes specify the semantics of a set accessor. They

Python: 浅淡Python中的属性(property)

起源:项目过程中需要研究youtube_dl这个开源组件,翻阅其中对类的使用,对比c#及Delphi中实现,感觉Python属性机制挺有意思.区别与高级编程语言之单一入口,在类之属性这一方面,它随意的太多,以致于习惯了高级语言的严谨,对如此随意心里倒是有些不安.也难怪,因为其数据类型弱限制性,往往一个函数返回了一个结果,追溯此返回值类型,有时需要费上许多工夫!我不是随意的人,但随意起来我还真不是人,用在此处,颇为贴切:b 属性,是对事物某种特性的抽象,面向对象编程中一个重要概念:区别于字段,它通

Objective - C中属性和点语法的使用

一.属性 属性是Objective—C 2.0定义的语法,为实例变量提供了setter.getter方法的默认实现能在一定程度上简化程序代码,并且增强实例变量的访问安全性 OC中的属性机制提供了便捷的设置和获取实例变量的方式,或者说属性提供了一个默认的设置器和访问器的实现:属性提供的方法是现实可配置的,属性的好处:相当于自己编写这一对方法,属性提供了一系列清晰分明的说明参数来定义设置器和访问器的行为,编译器可以根据你设置的说明参数为你生成相应的方法,减少你的代码量和维护工作量 设置器(sette

angular在模板中使用属性引发Cannot read property 'xxx' of undefined

在使用ng2的过程中,发现模板中如下方式 <li *ngFor="let item of model"> {{item.name}} </li> 不会又任何问题. 如果是一下未使用结构指令方式,直接使用组件的属性 <li > {{model.name}}</li> 就会报错null错误,一开始百思不得其解,后来搞明白,model是异步请求获取的数据,在定义的时候let mode:any 时是属于unde值,而这时组件模板已经开始渲染了,也

OC中对于属性的总结(@property)

在没有属性之前: 对成员变量进行改动都要用到设置器:setter来改动 Person *per =[[Person alloc] init]; 对象通过设置器对成员变量内容进行修该 [per setName:@"你好"]; 要通过訪问器:getter来进行取值 属性的出现 ,简化了代码 1.属性 属性是写在.h中 在XCode4.5之后,属性一共能够做了三件事: 1.声明了设置器:setter和訪问器:getter 2.实现了设置器和訪问器 3.声明了一个成员变量,成员变量命名会在属性

js中__proto__, property, prototype, 对象自身属性方法和原型中的属性方法的区别

__proto__: 这个属性是实例对象的属性,每个实例对象都有一个__proto__属性,这个属性指向实例化该实例的构造函数的原型对象(prototype). proterty:这个方法是对象的属性.(据说和一个对象的attr类似,比如dom对象中) prototype:每个构造函数都有一个prototype对象,这个对象指向该构造函数的原型. 对象自身属性方法和原型中的属性方法的区别: 对象自身的属性和方法只对该对象有效,而原型链中的属性方法对所有实例有效. 例子: function bas

objective C中继承、协议、分类和多态的实现

第一.objective C中继承的实现 在oc中只有实例变量会有权限控制,实例方法和类方法是没有权限控制的,这点与c++不同,OC默认的是protected,并且在声明权限控制时,没有分号 在OC中可以像C++一样用指针运算法来访问实例变量 Rectangle.h 文件代码: #import <Foundation/Foundation.h> @interface Rectangle : NSObject { int _width; int _height; } @property (non

Objective-C入门教程03:属性(@property和@synthesize)

在Java中,特别是一个标准的POJO类,我们定义了一些属性,然后针对每个属性生成相应的getter和setter.例如: package com.demo; /** * 手机类 * @author liuzc */ public class Phone { private String color; //颜色 private String os; //系统 private String brand; //品牌 /******* Getter & Setter *******/ public S

HTML5中meta属性

meta属性在HTML中占据了很重要的位置.如:针对搜索引擎的SEO,文档的字符编码,设置刷新缓存等.虽然一些网页可能没有使用meta,但是作为正规军,我们还是有必要了解一些meta的属性,并且能够熟练使用它们. 1.声明文档使用的字符编码 <meta charset='utf-8'> 2.声明文档的兼容模式 <meta http-equiv="X-UA-Compatible" content="IE=edge" /> 指示IE以目前可用的最