在Objective-C中的方法重载?

135
据我的了解,Objective-C不支持方法重载。在Objective-C中有什么替代方法吗?还是我应该总是使用不同的方法名?
3个回答

201

没错,Objective-C不支持方法重载,因此您必须使用不同的方法名。

需要注意的是,“方法名”包括方法签名关键字(出现在“:”之前的参数名称),因此以下两个以“writeToFile”开头的方法是完全不同的方法:

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

这两个方法的名称分别为 "writeToFile:fromInt:" 和 "writeToFile:fromString:"。


5
@RaheelSadiq,这并不是函数重载,因为方法名称(在ObjC中称为“selectors”)是不同的。由于它们不同,两个方法都不被认为是“overloaded”。如果只有参数types不同地定义了writeToFile:from:两次,则会发生函数重载。不过,与其他语言(包括Java和现在的Swift)不同,ObjC不支持此功能。 - Chris Hatton
不仅参数名称本身,甚至冒号也是方法名称的一部分,因此-(void) writeToFile:(NSString*)path :(int)anInt;和-(void) writeToFile:(NSString )path :(NSString)aString;也是不同的方法。 - Kaiserludi

22

值得一提的是,即使 Objective-C 不支持方法重载,但 Clang + LLVM 支持 C 语言的函数重载。虽然不完全符合您的需求,但在某些情况下可能会证明其有用(例如,在实现访问者设计模式的略微修改(违背了封装)的版本时)。

以下是一个简单的示例说明函数重载的工作方式:

__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:在手边时,这是另一回事... - Alex Gray
1
@alexgray 我理解你的观点,idisKindOfClass:可以涵盖大多数实际情况。你可能更喜欢重载的原因是自动选择最具体类型的功能,这需要显式类型检查来维护一些小开销。 - Chris Hatton
1
Clang文档明确表示,它所做的就是为C语言提供C++名称重载。这基本上只是编译器在幕后自动完成Objective-C中方法命名所做的事情,即通过包含(以更长的形式)参数类型来使方法名称具有区别性。 - Chris Stratton

20

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接