Objective-C 方法重写/重载混淆

3

似乎有一些争论/分歧,关于在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)ClassB 是从 ClassA 派生的,还是 B)不是。
2个回答

7

问题1:无法实现。Objective-C方法名称中不包含类型,没有混淆。如果使用Objective-C++可能可以——我没用过那么多。

问题2:同上。无法实现。

问题3:可以实现。

编辑:一般来说,方法名称不包含任何类型,因此如果你去掉了类型并且它们相同,则会被认为是相同的,因此不能在同一个类中允许。按照相同的思路,如果在不同的类中,它将起作用,但是如果调用中使用的类型和被调用的类型不太一致,可能会导致一些混乱。


好的,基本上字符串(例如)“methodWithParam1:param2:param3:”('selector')必须对于同一类中的每个方法都是唯一的,在子类化(覆盖)时更改参数类型/返回类型是可以的? - Nicolas Miari
1
很可能第三种情况会生成编译器警告。超类的方法需要一个ClassA的实例。这意味着该类及其子类的所有对象都必须接受相同方法中ClassA的任何对象。这是必要的,因为子类的实例可以在任何超类的实例可以使用的地方使用。但是您试图重新声明该方法,要求更窄-它只接受ClassB的对象。运行时,方法将被调用,但是否可以按照它所传递的参数工作是另一个问题。 - Ken Thomases
我想知道UITableView的delegate属性会发生什么。它应该重写UIScrollView的delegate属性,但进一步限制只接受符合UITableViewDelegate协议的对象。我不知道内部情况,但我确定你不能“覆盖”实例变量(ivars)。我假设在UITableView中,-setDelegate:属性访问器对传递的参数(参数)施加了额外的约束。 - Nicolas Miari

1

你正在以 C++ 的思维方式考虑,其中编译器通过根据输入的类型确定调用哪个实例方法来进行静态绑定。

Objective-C 的工作方式不同。在运行时,所有绑定都是动态的。有点像 C++ 中所有方法都声明为“虚函数”。程序员负责传递响应方法期望方式的适当变量。

如果您想要更强大的行为,您的方法可以查询传递的对象是否响应于某些选择器,并根据此采取适当的操作。或者您的方法可以询问传递的对象是否是它所期望的类型。这些都将在您的方法中在运行时完成,而不是由编译器完成。

因此,答案是声明为:

- (void) doSomethingWithObject:(id) object;

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


嗯,不是的...我绝对不是在考虑C++方面。我只是碰巧知道编译器会进行一些类型检查(当您指定除'id'以外的内容时),只是不知道其程度。 - Nicolas Miari

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