动态绑定似乎是一个谎言

bob*_*obo 6 objective-c dynamic-binding

Objective-C使用动态绑定:即在运行时解析方法调用.

精细.

使用点符号的真正归结为一个方法调用

但是,为什么我不能做这样的事情:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];


  // Intercept the exception
  @try
  {
    @throw [ NSException 
            exceptionWithName:@"Exception named ME!" 
            reason:@"Because i wanted to" 
            userInfo:nil ] ;
  }
  @catch( id exc ) // pointer to an exception object?
  {



    //NSLog( @"%@ : %@\n", exc.name, exc.reason ) ; // ILLEGAL:  Request for member 
    // 'name' in something not a structure or union..
    // If objective-c uses dynamic binding, and dot notation
    // boils down to calling the getter, then
    // WHY do I have to cast to the concrete type here?

    // Only works if I cast to the concrete type NSException*
    NSException* nexc = (NSException*)exc ;
    NSLog( @"%@ : %@\n", nexc.name, nexc.reason ) ;



  }



  [pool drain];
    return 0;
}

当我听到"动态绑定"时,我在想"所以它应该像脚本语言一样",而且我很惊讶Objective-C似乎与JavaScript之类的脚本语言相比.

Lou*_*arg 17

您对运行时和编译器感到困惑.运行时没有问题可以解决这个问题.问题是点符号(这是语法糖)需要编译器的类型信息来消除Objective-C对象和C结构之间的歧义.

如果你不使用点符号它的工作原理:

NSLog( @"%@ : %@\n", [exc name], [exc reason]) ;
Run Code Online (Sandbox Code Playgroud)

如果类型不是id,上面将生成警告,因为编译器知道它确实知道类型并且不能保证调度将起作用,但它将编译并运行.

从根本上说,编译器需要知道是否生成结构加载或Objective C调度,换句话说,使用点符号需要有足够的信息来确定对象和标量类型之间的差异.


bbu*_*bum 17

动态绑定不是动态类型的同义词.C是一种强类型语言,特别是参数或返回值的类型很重要,可能会严重影响代码生成.

属性专门用于消除歧义.作为其中的一部分,该决定将不会允许对使用的点语法id.

具体来说,它解决了这种情况:

@interface Foo
- (short) length;
@end

@interface Bar
- (unsigned long long) length;
@end
Run Code Online (Sandbox Code Playgroud)

鉴于以上两个单独的头文件,编译[anObject length]只会警告两个头文件都已导入.如果只导入了一个头文件,则将编译调用站点,返回标题中看到的类型.如果调用站点用于另一个方法,则将返回非常意外的结果.

点语法的限制消除了这种潜在的模糊性.这也是您通常不会看到方法的共变量声明的原因.C ABI只是不干净地支持它(据说,Objective-C在支持对象类型协方差方面表现不佳).

实际上,Objective-C开发人员很少使用该id类型.特定类型声明使编译器能够显着改进其代码验证.