【问题标题】:Method overloading in Objective-C?Objective-C中的方法重载?
【发布时间】:2011-01-18 04:23:19
【问题描述】:

据我所知,Objective-C 不支持方法重载。在 Objective-C 中有什么替代方法?还是我应该总是使用不同的方法名?

【问题讨论】:

    标签: ios objective-c overloading


    【解决方案1】:

    正确,objective-C 不支持方法重载,所以你必须使用不同的方法名。

    但请注意,“方法名称”包括方法签名关键字(参数 ":"s) 之前的名称,因此以下是两个不同的 方法,即使它们都以“writeToFile”开头:

    -(void) writeToFile:(NSString *)path fromInt:(int)anInt;
    -(void) writeToFile:(NSString *)path fromString:(NSString *)aString;
    

    (这两个方法的名称分别是“writeToFile:fromInt:”和“writeToFile:fromString:”)。

    【讨论】:

    • @RaheelSadiq 它没有重载,因为方法名称(在 ObjC 中:“选择器”)不同。不同的是,两者都不被认为是“超载”。如果 writeToFile:from: 被定义了两次,只有参数 types 不同,那么这将是重载。如前所述,这在 ObjC 中不受支持,就像在其他语言中一样,包括 Java 和现在的 Swift。
    • 不只是参数名本身,连冒号也是方法名的一部分,所以 -(void) writeToFile:(NSString*)path :(int)anInt;和 -(void) writeToFile:(NSString )path :(NSString)aString;也是不同的方法。
    【解决方案2】:

    可能值得一提的是,即使 Objective-C 不支持 方法 重载,Clang + LLVM 确实支持 C 的 函数 重载。虽然不完全是你'正在寻找,它在某些情况下可能会被证明是有用的(例如,当实现visitor design pattern一个稍微被破解的(反对封装)版本时)

    这是一个关于函数重载如何工作的简单示例:

    __attribute__((overloadable)) float area(Circle * this)
    {
        return M_PI*this.radius*this.radius;
    }
    
    __attribute__((overloadable)) float area(Rectangle * this)
    {
        return this.w*this.h;
    }
    
    //...
    //In your Obj-C methods you can call:
    NSLog(@"%f %f", area(rect), area(circle));
    

    【讨论】:

    • 有人会认为这个提示,结合方法调配,确实会导致“可重载”的方法......为什么需要idisKindOfClass: 可以随意使用, 是另一回事...
    • @alexgray 我明白你的意思,idisKindOfClass: 涵盖了大多数实际场景。您可能更喜欢重载的一个原因是自动选择最适合的类型,这会产生少量开销来维护显式类型检查。
    • Clang 文档明确指出,它所做的是为 C 提供 C++ 名称修饰。这基本上只是编译器自动在幕后执行在 Objective-C 中所做的事情,方法是提供以下方法名称通过包含(较长形式)参数类型来区分。
    【解决方案3】:

    David 是正确的,Objective-C 不支持方法重载。从这个意义上说,它类似于 PHP。正如他还指出的那样,以他示例的方式定义两个或多个具有不同签名的方法是常见的做法。但是,也可以使用“id”类型创建一种方法。通过“id”类型,您可以将任何对象(以及使用 NSNumber 类的任何原语)发送到该方法,然后您可以在方法本身内部测试其类型并在必要时抛出适当的异常。尽管这确实对性能有轻微影响,但除非您处理大量数据,否则它很可能是名义上的或微不足道的。

    - (void) writeToFile: (NSString *)path fromObject: (id)object {
        if (!([object isKindOfClass: [NSNumber class]] || [object isKindOfClass: [NSString class]])) {
             @throw [NSException exceptionWithName: @"InvalidArgumentException" reason: @"Unrecognized parameter type." userInfo: nil];
        }
    }
    

    这也是一个执行对象类型协议的好地方,可以这样做:

    (id<MyProtocol>)object
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-12
      • 1970-01-01
      • 2014-09-13
      • 1970-01-01
      • 2014-12-31
      相关资源
      最近更新 更多