2016-06-30 2 views
3

Почему следующий фрагмент кода ТОЛЬКО печать blah3 и blah4, но не blah2?NSMutableDictionary isKindOfClass NSDictionary is false

isKindOfClass должен уважать наследование, но, похоже, это не так.

Obj-C:

NSDictionary *dict = [NSDictionary new]; 
NSMutableDictionary *mutableDict = [NSMutableDictionary new]; 

if([dict isKindOfClass:[mutableDict class]]){ 
    NSLog(@"blah"); //does not print (as expected) 
} 

if([mutableDict isKindOfClass:[dict class]]){ 
    NSLog(@"blah2"); //does not print (unexpected!) 
} 

if([mutableDict isKindOfClass:[mutableDict class]]){ 
    NSLog(@"blah3"); //prints 
} 

if([dict isKindOfClass:[dict class]]){ 
    NSLog(@"blah4"); //prints 
} 

Свифта:

var dict = NSDictionary() 
var mutableDict = NSMutableDictionary() 
if(dict.isKindOfClass(mutableDict.dynamicType)) {print("blah")} 
if(mutableDict.isKindOfClass(dict.dynamicType)) {print("blah2")} 
if(dict.isKindOfClass(dict.dynamicType)) {print("blah3")} 
if(mutableDict.isKindOfClass(mutableDict.dynamicType)) {print("blah4")} 

Использование Xcode 7.3.1, IOS, 9.3.

ответ

3

Причина в том, что NSDictionary.new не гарантирует возврат самого NSDictionary - он может вернуть подкласс. И ваш dict, похоже, относится к подклассу, например, NSDictionary0. Кроме того, изменчивый, вероятно, является подклассом NSMutableDictionary, например NSMutableDictionaryM.

Так что ваш NSMutableDictionary действительно является NSDictionary, но не он не наследуется от этого другого подкласса.

Вы можете легко проверить это с помощью isKindOf:[NSDictionary class]. Вы можете захотеть сбросить или осмотреть классы ваших конкретных объектов и удивиться.

Edit: вот быстрая и грязная диаграмма классов: enter image description here

Как вы можете видеть, один не «вид» другой, хотя оба NSDictionary.

Это называется классовым кластером и имеет некоторые сложные последствия. NSString - это еще одна известная, где классы редко бывают ожидаемыми новичками.

+0

Не уверен, что вы говорите. Если NSMutableDictionary является NSDictionary, почему бы не печатать blah2? – user1366911

+0

Потому что вы сравниваете с 'dict.class'. Но dict - это не 'NSDictionary', а подкласс. – Eiko

+0

Как насчет usecase, где у меня есть два идентификатора, и я хочу проверить, являются ли классы одинаковыми или подклассами. В этом случае мне нужно использовать isKindOfClass. Я не могу сравнивать непосредственно с [классом NSDictionary]. Это цель isKindOfClass, нет? – user1366911

Смежные вопросы