Ios 为什么KindOfClass和isMemberOfClass在NSString和NSMutableString中工作不好?
我知道反对使用它。但考虑到他们的推理,结果与预期相差甚远 这是我的调试输出-结果在代码中没有差异-以下仅为简洁起见:Ios 为什么KindOfClass和isMemberOfClass在NSString和NSMutableString中工作不好?,ios,class,nsstring,objective-c-runtime,nsmutablestring,Ios,Class,Nsstring,Objective C Runtime,Nsmutablestring,我知道反对使用它。但考虑到他们的推理,结果与预期相差甚远 这是我的调试输出-结果在代码中没有差异-以下仅为简洁起见: (lldb) po [@"Hello" isKindOfClass:[NSMutableString class]] true => A mutable string? (lldb) po [[@"Hello" mutableCopy] isKindOfClass:[NSMutableString class]] 0x00000001019f3201 => Wh
(lldb) po [@"Hello" isKindOfClass:[NSMutableString class]]
true => A mutable string?
(lldb) po [[@"Hello" mutableCopy] isKindOfClass:[NSMutableString class]]
0x00000001019f3201 => What's that?
(lldb) po [[@"Hello" mutableCopy] isMemberOfClass:[NSMutableString class]]
0x000000010214e400 => What's that?
(lldb) po [@"Hello" isMemberOfClass:[NSMutableString class]]
false => Once again?
此外,我删除了所有字符串文字代码,并测试了以下内容:
NSMutableString * m = [[NSMutableString alloc] initWithString:@"Hello"];
bool b = [m isKindOfClass:[NSMutableString class]];
NSLog(@"%d", b); --> 1 Expected.
b = [m isKindOfClass:[NSString class]];
NSLog(@"%d", b); --> 1 Expected.
b = [m isMemberOfClass:[NSString class]];
NSLog(@"%d", b); --> 0 Expected.
b = [m isMemberOfClass:[NSMutableString class]];
NSLog(@"%d", b); --> 0 Not Expected.
有什么启示吗
更新:
苹果自己的观点:
在类表示的对象上使用此方法时要小心
簇由于类簇的性质,您得到的对象
back可能并不总是您所期望的类型。如果你调用一个方法
返回一个类集群,方法返回的确切类型为
你能用这个物体做什么的最佳指示器
为什么不简单地说不要使用集群类使用isKindOfClass
和isMemberOfClass
该解释禁止从以下角度使用:
你可能会修改一些你不应该修改的东西
而不是说:
这些方法不适用于类集群。
(在上面的示例中,我已经展示了-我显然传递了正确的对象,但仍然没有得到预期的结果。)
更新2:
提交给。这些方法不会像您在评论中声称的那样“误导”。由于NSString
和NSMutableString
是类集群,因此它们可以分别返回任何具体子类的实例,即NSString
或NSMutableString
碰巧,NSString
集群中的大多数具体子类也是NSMutableString
的子类。它们不使用实际的类来控制可变性,而是使用标志或类似的东西。所有文件均完全有效,并符合设计合同的规定
所以,这就是为什么[@“Hello”是类:[NSMutableString类]]
返回true。你问“一个可变字符串?”没有。这个表达式不是一个有效的可变测试。如文件所述,没有有效的可变性测试。这是你误解的核心。您不能试图询问对象的类以确定它是否是可变的。您必须尊重API中指针的静态类型
编辑:这记录在: 使用返回类型,而不是内省 要确定是否可以更改接收到的对象,则 消息必须依赖于返回值的形式类型。如果是 例如,接收类型为不可变的数组对象时,它应该 不要试图改变它。这不是一种可接受的编程实践 根据对象的类成员身份确定对象是否可变 例如:
if ( [anArray isKindOfClass:[NSMutableArray class]] ) {
// add, remove objects from anArray
}
出于与实现相关的原因,isKindOfClass:
在
这种情况可能并不准确。但除此之外的原因,你
不应假设对象是否是基于可变的
关于班级成员资格。你的决定应该完全以
出售对象的方法的签名说明了对象的可变性。
如果您不确定对象是可变的还是不可变的,请假定
它是不变的
下面的几个例子可能有助于澄清为什么这条准则是正确的
重要:
- 从文件中读取属性列表。当基础框架处理列表时,它会注意到不同的子集。 属性列表是相同的,因此它会创建一组对象,并 所有这些子集之间的份额。之后,您将查看创建的 属性列出对象并决定对一个子集进行变异。突然,而且 不知不觉中,您已在多个位置更改了树
- 您向
询问它的子视图(使用NSView
方法),它返回一个声明为subviews
但可能是 内部的NSArray
。然后将该数组传递给其他数组 代码,通过内省确定它是可变的,并且 改变它。通过更改此数组,代码将改变内部数据NSMutableArray
类的结构NSView
正如其他人所提到的,
-isMemberOfClass:
测试是否是该类的实例,而不是任何子类。对于类集群,这将始终返回false,因为公共类是抽象的,永远不会有实例
其他奇怪的结果可能是因为您使用了po
(print object的缩写)作为非对象值。对布尔表达式使用p
命令。这些方法不会像您在注释中所说的那样“误导”。由于NSString
和NSMutableString
是类集群,因此它们可以分别返回任何具体子类的实例,即NSString
或NSMutableString
碰巧,NSString
集群中的大多数具体子类也是NSMutableString
的子类。它们不使用实际的类来控制可变性,而是使用标志或类似的东西。所有文件均完全有效,并符合设计合同的规定
所以,这就是为什么[@“Hello”是类:[NSMutableString类]]
返回true。你问“一个可变字符串?”没有。这个表达式不是一个有效的可变测试。如文件所述,没有有效的可变性测试。这是该计划的核心