zoukankan      html  css  js  c++  java
  • 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预编译指令的作用是自动声明属性的settergetter方法,事实上,属性的名称不必与实例变量的名称相同,但大多数情况下它们是一样的。

    我们知道了函数的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 =@“Car” 改成self.name =@"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方法的一种便捷方式。点表达式法减少了需要键入的字符数量,而且进一步方便了曾经使用其他语言的编程人员。

  • 相关阅读:
    Eclipse debug模式下使用16进制(Hex)查看变量值
    无线局域网中RADIUS协议原理与实现
    浏览器发送URL的编码特性
    跨域共享cookie和跨域共享session
    Nginx与Apache工作方式
    Http字段含义
    http中有关缓存相关的几个字段
    maven中用yuicompressor和closure-compiler对js、css文件进行压缩
    Mysql 忘记密码----修改Navicat的连接密码--以及--(加入安装Navicat时没设置密码)有时新建连接设置密码,连接不成功---的问题解决方法 密码忘记的解决
    RedisTemplate的各种操作(set、hash、list、string)
  • 原文地址:https://www.cnblogs.com/xinianhao/p/3759359.html
Copyright © 2011-2022 走看看