Objective-c的优点

本文要点:
1:isa指针
2:动态能力(运行时决定)
3: 范畴( categories ------- 为某个类添加方法而又不必制作子类
4: 协议(protocols)-------非常相似java中的接口Interface

-----------------------------------------------------------------
每个Objective-C对象都隐藏着一个数据结构,它的第一个成员变量—或者说是实例变量—是“isa指针”。
isa指针指向的是对象的类,这个类也是一个对象,有自己的权限(参见图2-1),是根据类的定义编译而来的。
类对象负责维护一个方法调度表,该表本质上是由指向类方法的指针组成的;
类对象中还保留一个超类的指针,该指针又有自己的方法调度表和超类(还有所有通过继承得到的公共和保护的实例变量)。
An object’s isa pointer
-------------------------------------------------------------------------------------------------------------------
动态能力使程序可以突破编译和连接时的约束,将更多符号辨识的工作转移到处于受控状态的运行环境上。


动态类—在运行时确定对象的类      id数据类型,

表示任意的Cocoa对象,可通过 内省在运行时确定所属的类。

动态绑定—在运行时确定要调用的方法  

运行时的消息分发机制

动态装载—在运行时为程序增加新的模块  

Cocoa程序可以在需要的时候才装载执行代码和资源
----------------------------------------------------------------------------------------------------------
范畴
范畴提供一种为某个类添加方法而又不必制作子类的途径。范畴中的方法会变成类的一部分(在您的应用程序的作用域内),并为该类的所有子类所继承。在运行时,原始方法和通过范畴添加的方法之间没有差别,您可以向类(或者它的子类)实例发送消息,以调用范畴中定义的方法。
范畴不仅是一种为类添加行为的便利方法,还可以对方法进行分组,将相关的方法放在不同的范畴中。范畴对于组织规模大的类特别方便,例如当几个开发者同时在一个类上工作时,您甚至可以将不同的范畴放在不同的源文件中。
范畴的声明和实现很象子类。在语法上,唯一的区别是范畴的名称需要跟在@interface@implementation导向符之后,且放在园括号中。举例来说,假定您希望为NSArray类增加一个方法,以便用更加结构化的方式打印集合的描述。那么您可以在范畴的头文件中书写如下的声明代码:
  • #import <Foundation/NSArray.h> // if Foundation not already imported
    
     
    
    @interface NSArray (PrettyPrintElements)
    
    - (NSString *)prettyPrintDescription;
    
    @end
    

    然后在实现文件中书写如下代码:

    #import "PrettyPrintCategory.h"
    
     
    
    @implementation NSArray (PrettyPrintElements)
    
    - (NSString *)prettyPrintDescription {
    
        // implementation code here...
    
    }
    
    @end
    

    范畴有一些限制。您不能通过范畴为类添加新的实例变量。虽然范畴方法可以覆盖现有的方法,但这并不是推荐的做法,特别是当您希望对现有行为进行增强的时候。一个原因是范畴方法是类接口的一部分,因此无法通过向super发送消息来获取类中已经定义的行为。如果您需要改变一个类的现有方法的行为,更好的方法是生成一个该类的子类。

    您可以通过范畴来为根类—NSObject—添加方法。通过这种方式添加的方法可以用于与该代码相连接的所有实例和类对象。非正式的协议—Cocoa委托机制的基础—在NSObject类中声明为范畴。然而,这种在使用上的广泛适用也有它的风险。您通过范畴向NSObject添加的行为可能会有意料不到的结果,可能导致崩溃,数据损坏,甚至更坏的结果。

    --------------------------------------------------------------------------------------------------------------------------------------------

     

    协议

    Objective-C的另一个扩展称为协议,它非常象Java中的接口。两者都是通过一个简单的方法声明列表发布一个接口,任何类都可以选择实现。协议中的方法通过其它类实例发送的消息来进行调用。

    协议的主要价值和范畴一样,在于它可以作为子类化的又一个选择。它们带来了C++多重继承的一些优点,使接口(如果不是实现的话)可以得到共享。协议是一个类在声明接口的同时隐藏自身的一种方式。接口可以暴露一个类提供的所有(通常是这种情况)或部分服务。类层次中的其它类都可以通过实现协议中的方法来访问协议发布的服务,不一定和协议类有继承关系(甚至不一定具有相同的根类)。通过协议,一个类即使对另一个类的身份(也就是类的类型)一无所知,也可以和它进行由协议定义的特定目的的交流。

    有两种类型的协议:正式和非正式协议。非正式协议在"范畴"部分中已经简单介绍了,它们是NSObject类中定义的范畴。因此每个以NSObject为根类的对象(和类对象)都隐式采纳了范畴中发布的接口。和正式协议不同,一个类不必实现非正式协议中的每个方法,而是只实现它感兴趣的方法就可以了。为了使非正式协议正确工作,声明非正式协议的类在向某个目标对象发送协议消息之前,必须首先向它发送respondsToSelector: 消息并得到肯定的回答(如果目标对象没有实现相应的方法,则产生一个运行时例外)。

    Cocoa中的“协议”通常指的是正式协议。它使一个类可以正式地声明一个方法列表,作为向外提供服务的接口。Objective-C语言和运行系统支持正式协议;编译器可以根据协议进行类型检查,对象可以在运行时进行内省,以确认是否遵循某个协议。正式协议有自己的专用术语和语法。术语方面,提供者和客户的意义有所不同:

    • 提供者(通常是一个类)声明正式的协议。

    • 客户类采纳正式协议,表示客户类同意实现协议中所有的方法。

    • 如果一个类采纳某协议或者是从采纳该协议的类派生出来的(协议可以被子类继承),则可以说该类遵循协议。

    在Objective-C中,声明和采纳协议都有自己的语法。协议的声明必须使用编译导向符@protocol。下面的例子显示了NSCoding协议(在Foundation框架的NSObject.h头文件中)的声明方式:

    
    @protocol NSCoding
    
    - (void)encodeWithCoder:(NSCoder *)aCoder;
    
    - (id)initWithCoder:(NSCoder *)aDecoder;
    
    @end
    

    协议的声明类不需要实现这些方法,但应该对遵循该协议的对象方法进行调用。

    如果一个类要采纳某个协议,需要在在@interface导向符后、紧接着超类的位置上指定协议的名称,并包含在尖括号中。一个类可以采纳多个协议,不同的协议之间用逗号分隔。下面是Foundation框架中的NSData类采纳三个协议的方式:

    @interface NSData : NSObject <NSCopying, NSMutableCopying, NSCoding>
    

    通过采纳这些协议,NSData许诺自己要实现协议中声明的所有方法。范畴也可以采纳协议,对协议的采纳将成为类定义的一部分。

    Objective-C通过类遵循的协议和类继承的超类来定义类的类型。您可以通过发送conformsToProtocol:消息来检查一个类是否遵循特定的协议:

    if ([anObject conformsToProtocol:@protocol(NSCoding)]) {
    
            // do something appropriate
    
    }
    

    在类型声明—方法、实例变量、或函数中,您可以将遵循的协议作为类型的一部分来指定。这样您就可以通过编译器来得到另一个级别的类型检查,这种检查比较抽象,因为它不和特定的实现相关联。您可以使用与协议采纳相同的语法规则,即把协议的名称放在尖括号中,通过这种语法可以在类型中指定遵循的协议。您常常会看到在这些声明中使用了动态对象类型id,例如:

    - (void)draggingEnded:(id <NSDraggingInfo>)sender;
    

    这里,参数中引用的对象可以是任意类型的类,但是必须遵循NSDraggingInfo协议。

    除了目前为止已经提到的协议之外,Cocoa还提供了几个协议的例子。一个有趣的例子就是NSObject协议。可以想象得到的是,NSObject类采纳了这个协议,还有一个根类—NSProxy—也采纳了这个协议。通过这个协议,NSProxy类可以和Objective-C运行环境的一部分进行交互,包括引用计数、内省、和对象行为的其它基础部分。

    正式协议有其自己的限制。如果协议声明的方法列表随着时间而增长,协议的采纳者就会不再遵循该协议。因此,Cocoa中的正式协议被用于稳定的方法集合,比如NSCopyingNSCoding。如果您预期协议方法会增多,则可以声明为非正式协议,而不是正式协议


    本文摘自

    http://www.apple.com.cn/developer/mac/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/chapter_3_section_3.html#//apple_ref/doc/uid/TP40002974-CH4-DontLinkElementID_66

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值