【问题标题】:Question about isKindOfClass关于 isKindOfClass 的问题
【发布时间】:2011-09-06 21:16:54
【问题描述】:

请看这段代码被剪断

- (SoapRequest*)AddFlyData:(id)_target 
                    action:(SEL)_action 
                 sessionid:(int)sessionid 
                  datasets:(FlyNetArrayOfDataSet*)datasets
{
    if ([datasets isKindOfClass:[FlyNetArrayOfDataSet class]]) {
        NSLog(@"Yeah");
    } else {
        NSLog(@"Not Yeah");
    }
}

为什么,当我查看控制台时,我得到了

2011-09-06 23:08:00.917 soap-test[2133:207] Not Yeah

我是一个初学者,我完全糊涂了.. :s 当我查看调试器时,变量类型是 SoapArray(它是 FlyNetArrayOfDataSet 的父类)。

我使用 SoapArray 中的一个方法来启动我的“数据集”实例,这意味着该类被自动定义为 Soap 而不是 FlyNetArrayOfDataSet?!

谢谢

编辑:我犯了一个错误,它不是 NSArray 而是继承自 SoapArray

这是 FlyNetArrayOfDataSet 类的头文件

#import "Soap.h"

@interface FlyNetArrayOfDataSet : SoapArray
{
}

+ (NSMutableString*) serialize: (NSArray*) array;

@end

但这并不能解释为什么 isKindOfClass 返回 false ..

EDIT2:好的,我已经回答了我的问题..

我用这个方法来初始化我的实例

FlyNetArrayOfDataSet * arr = [FlyNetArrayOfDataSet arrayWithObject:data];

这是超类 SoapArray 的静态方法,它创建 SoapArray (Helper) 的实例 .. 但不是 FlyNetArrayOfDataSet (!) 的实例

看看它的实现:

+ (id)arrayWithObjects:(id)firstObj, ...{
    SoapArray* a = [SoapArray array];
    id eachObject;
    va_list argumentList;
    if (firstObj) {
        [a.items addObject: firstObj];
        va_start(argumentList, firstObj);
        while (eachObject = va_arg(argumentList, id)) {
            [a.items addObject: eachObject];
        }
        va_end(argumentList);
    }
    return a;
}

如果我像这样初始化我的实例

FlyNetArrayOfDataSet * arr = [[FlyNetArrayOfDataSet alloc] init];

它工作得很好,方法 isKindOfClass 返回 true :-)

【问题讨论】:

  • 父类是指对象的类,还是超类?你不应该继承 NSArray。
  • 举一个你调用这个方法的例子。仅仅因为该方法需要某种类型的对象并不意味着这就是您给它的类型。
  • WTP 说的是对的,永远不会从类集群中继承。它会导致痛苦和软件不稳定。

标签: objective-c


【解决方案1】:

假设您有一个名为“FlyNetArrayOfDataSet”的类,它继承自 NSArray(= 是其子类)。

如果你实例化一个像这样的变量:

FlyNetArrayOfDataSet *arr = [[FlyNetArrayOfDataSet alloc] init];

如您所见,我正在使用 NSArray 方法初始化数组。但是,我的“arr”对象将属于 FlyNetArrayOfDataSet,而不是 NSArray,因为我调用了 FlyNetArrayOfDataSet 类(参见 [FlyNetArrayOfDataSet arrayWithObject....)。

NSLog(@"%d", [arr isKindOfClass:[FlyNetArrayOfDataSet class]]);
NSLog(@"%d", [arr isKindOfClass:[NSArray class]]);

两者都会返回“1”,表示“真”,因为arr是FlyNetArrayOfDataSet类的对象,继承自NSArray。

编辑 让我们看看我是否可以更好地解释它:

arr1 = [[FlyNetArrayOfDataSet alloc] init];
arr2 = [[NSArray alloc] init];

arr1 和 arr2 这两个对象都是使用相同的方法创建的,该方法在 NSArray 类中定义。但是,在第一种情况下,被调用的类是 FlyNetArrayOfDataSet,在第二种情况下是 NSArray。因此,arr1 将是 FlyNetArrayOfDataSet 类的对象,而arr2 将是 NSArray 类的对象。

在这段代码中可以看出区别:

NSLog(@"%d %d",
    [arr1 isKindOfClass:[FlyNetArrayOfDataSet class]]
    [arr1 isKindOfClass:[NSArray class]]
);
NSLog(@"%d %d",
    [arr2 isKindOfClass:[FlyNetArrayOfDataSet class]]
    [arr2 isKindOfClass:[NSArray class]]
);

这段代码的输出是:

1 1 ( = true true)
0 1 ( = false true)

【讨论】:

  • 取决于NSArray如何在arrayWithObject方法中创建对象!
  • 这一直对我有用,至少对于系统框架中的类。他看起来已经很困惑,可以用这些边缘情况来打扰他,在使用 Foundation 类时并不重要:)
  • 这实际上是行不通的。您必须覆盖initWithObjects:count:,因为arrayWithObject: 调用它并且它只为抽象类定义(NSArray 将引发异常)。作为一个类集群,子类NSArray 通常是个坏主意,尤其是对于初学者。
  • 当然,我同意......但也许你应该在你的答案中添加一个注释,因为它已经很详细了。还告诉他在有疑问时使用 NSStringFromClass 来调试对象的真实类... :)
  • omz,你是对的。我正在尝试查看是否可以使用不会出现此问题的其他方法。
【解决方案2】:

那是因为 FlyNetArrayOfDataSetSoapArraySoapArray 不是 FlyNetArrayOfDataSet

如果datasetsSoapArray 的一个实例,您将在以下示例中看到“Soap”:

- (SoapRequest*)addFlyData:(id)target
                    action:(SEL)action
                 sessionid:(int)sessionid
                  datasets:(FlyNetArrayOfDataSet*)datasets
{
    if ([datasets isKindOfClass:[FlyNetArrayOfDataSet class]]) {
        NSLog(@"Fly");
    }
    else if ([datasets isKindOfClass:[SoapArray class]]) {
        NSLog(@"Soap");
    }
    else {
        NSLog(@"???");
    }
}

SoapArray 的实例可能也是FlyNetArrayOfDataSet。其他可能性是:

  • SoapArray
  • FlyNetArrayOfDataSet 以外的子类。

【讨论】:

  • 请参阅我的问题的EDIT2
  • 试试SoapArray* a = [self array];
猜你喜欢
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-29
  • 2011-09-22
  • 2018-05-23
  • 2011-11-16
相关资源
最近更新 更多