您遇到的问题的关键在于关于 Objective-C 中的多态性的一个微妙点。因为该语言不支持方法重载,所以假定方法名称唯一标识给定类中的方法。有一个隐含的(但重要的)假设,即被覆盖的方法与它所覆盖的方法具有相同的语义。
在您给出的情况下,可以说两种方法的语义不同;即,第一种方法返回一个新字符串,该字符串用接收者内容的“剥离”版本初始化,而第二种方法直接修改接收者的内容。这两个操作真的不等价。
我认为,如果您仔细研究一下 Apple 命名其 API 的方式,尤其是在 Foundation 中,它确实有助于阐明一些语义上的细微差别。例如,在 NSString 中有几种方法可以创建一个包含修改版本的接收器的新字符串,例如
- (NSString *)stringByAppendingFormat:(NSString *)format ...;
请注意,名称是一个名词,其中第一个单词描述返回值,名称的其余部分描述参数。现在将其与 NSMutableString 中的相应方法进行比较,以直接附加到接收器:
- (void)appendFormat:(NSString *)format ...;
相比之下,这个方法是一个动词,因为没有返回值来描述。因此,仅从方法名称就可以清楚地看出 -appendFormat: 作用于接收者,而 -stringByAppendingFormat: 不作用,而是返回一个新字符串。
(顺便说一句,NSString 中已经有一个方法至少可以完成您想要的部分功能:-stringByTrimmingCharactersInSet:
。您可以将whitespaceCharacterSet
其作为参数传递以修剪前导和尾随空格。)
因此,虽然一开始可能看起来很烦人,但我认为从长远来看,尝试效仿 Apple 的命名约定真的很值得。如果不出意外,它将有助于使您的代码更具自文档性,尤其是对于其他 Obj-C 开发人员。但我认为它也有助于澄清 Objective-C 和 Apple 框架的一些语义上的微妙之处。
另外,我同意类集群的内部细节可能令人不安,特别是因为它们对我们来说大多是不透明的。然而,事实仍然是 NSString 是一个类集群,它使用 NSCFString 来表示可变和不可变实例。因此,当您的第二个类别添加另一个-strip
方法时,它会替换-strip
第一个类别添加的方法。更改一个或两个方法的名称将消除此问题。
而且由于 NSString 中已经存在提供相同功能的方法,可以说您只需添加可变方法即可。理想情况下,它的名称应与现有方法相对应,因此应为:
- (void)trimCharactersInSet:(NSCharacterSet *)set