【问题标题】:Objective-C method overriding/overloading confusionObjective-C 方法覆盖/重载混淆
【发布时间】:2012-07-08 14:05:26
【问题描述】:

对于是否可以在 Objective-C 中“重载”方法似乎存在一些争论/分歧。撇开在 Objective-C 中定义方法重载的术语与 C++ 中的术语相同(因为方法签名语法不同)是不可能的,我要特别问:以下哪些是允许的,哪些是不允许的?

1) 声明/实现这两种方法的类:

- (void) doSomethingWithObject:(ClassA*) object;
- (void) doSomethingWithObject:(ClassB*) object;

2) 声明/实现这两种方法的类:

- (void) doSomethingWithObject:(ClassA*) object;
- (BOOL) doSomethingWithObject:(ClassA*) object;

3) 声明/实现此方法的类:

- (void) doSomethingWithObject:(ClassB*) object;

...当它的超类声明/实现这个方法时:

- (void) doSomethingWithObject:(ClassA*) object;

(以及冲突返回值的类似物),当 A)ClassBClassA 下降,而 B)不是。

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    问题 1:不可以:Objective-C 不包括方法名称中的类型;没有损坏。它可能适用于 Objective-C++ —— 从来没有用过那么多。

    问题 2:相同。不会工作。

    问题 3:可行。

    编辑:通常,方法名称不包含任何类型,因此如果您剥离类型并且它们相同,那么它将被视为相同,因此不允许在同一个类中。同样,如果它位于不同的类中,它将起作用,尽管如果调用中使用的类型和被调用的类型不完全一致,您可能会感到困惑。

    【讨论】:

    • 好的,所以基本上字符串(例如)“methodWithParam1:param2:param3:”(“选择器”)对于同一类中的每个方法必须是唯一的,并且在更改参数类型/返回类型时子类化(覆盖)可以吗?
    • 情况 3 很可能会生成编译器警告。超类的方法采用ClassA 的实例。这意味着该类及其子类的所有对象都必须接受ClassA 的任何对象以用于相同的方法。这是必要的,因为子类的实例可以在超类实例可能存在的任何地方使用。但是您正试图以更窄的要求重新声明该方法——它只接受ClassB 的对象。正确的是,在运行时,该方法将被调用,但考虑到它传递的内容,它是否会起作用是另一个问题。
    • 我想知道 UITableView 的委托属性会发生什么。它应该覆盖 UIScrollView 的委托属性,但它进一步限制它只接受也符合 UITableViewDelegate 协议的对象。我不知道内部情况,但我敢肯定你不能“覆盖” ivars。我假设 UITableView 中的 -setDelegate: 属性访问器在传递的参数(参数)中施加了额外的约束。
    【解决方案2】:

    您正在考虑 C++,其中编译器执行静态绑定,根据输入的类型确定要调用的实例方法。

    Objective-C 不是这样工作的。相反,所有绑定在运行时都是动态的。有点像在 C++ 中声明为“虚拟”的所有方法。程序员负责传入适当的变量,这些变量以您的方法所期望的方式响应。

    如果您想要更健壮的行为,您的方法可以查询传入的对象是否响应某些选择器并基于此采取适当的操作。或者您的方法可以询问传入的对象是否是它期望的类型。同样,这一切都将在您的方法的运行时完成。不是由编译器决定的。

    所以答案是,声明为:

    - (void) doSomethingWithObject:(id) object;
    

    ...然后传入你喜欢的任何对象。

    【讨论】:

    • 呃,不......我绝对不会考虑 C++。我只是碰巧知道编译器会做一些类型检查(当你指定除 'id' 以外的东西时),只是不知道范围。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多