【问题标题】:Object orientation - iOS isEqual method in superclass, will it work correctly for subclasses?面向对象 - 超类中的 iOS isEqual 方法,它是否适用于子类?
【发布时间】:2014-01-24 11:12:02
【问题描述】:

我有两个isEqual 方法,看起来像这样:

- (BOOL)isEqualToObject:(IdentifiableObject *)object {
    if ([self identifier] == [object identifier])
        return YES;
    return NO;
}

- (BOOL)isEqual:(id)otherObject {
    if (otherObject == self)
       return YES;
    else if (!otherObject || ![otherObject isKindOfClass:[self class]])
       return NO;
    return [self isEqualToObject:otherObject];
}

这被放置在其他类继承自的通用超类中。

这会按预期(或按我的意愿)工作吗?还是应该将isEqual 方法放在每个子类中?

【问题讨论】:

    标签: ios objective-c oop inheritance


    【解决方案1】:

    由于您的子类将继承此方法,因此它可以按预期工作。在您的isEqual: 方法中,您使用了self,因此您指的是当前类实例。

    这里是一个例子:

    @interface ClassA : NSObject
    
    @property (nonatomic,strong) NSString* myName;
    
    @end
    
    // -------
    
    @implementation ClassA
    
    - (BOOL)isEqualToObject:(ClassA *)object {
        if (self.myName == object.myName)
            return YES;
        return YES;
    }
    
    - (BOOL)isEqual:(id)otherObject {
        if (otherObject == self)
            return YES;       // instead of "![otherObject isKindOfClass:[self class]]"
        else if (!otherObject || !([otherObject class] == [self class]))
            return NO;
        return [self isEqualToObject:otherObject];
    }
    
    @end
    

    示例用法

    ClassA* a1 = [[ClassA alloc]init];
    ClassA* a2 = [[ClassA alloc]init];
    a1.myName  = @"joe";
    a2.myName  = @"joe";
    
    ClassB* b1 = [[ClassB alloc]init];
    ClassB* b2 = [[ClassB alloc]init];
    b1.myName  = @"frank";
    b2.myName  = @"frank";
    
    ClassC* c1 = [[ClassC alloc]init];
    ClassC* c2 = [[ClassC alloc]init];
    c1.myName  = @"donnie";
    c2.myName  = @"donnie";
    
    NSLog(@" a1 == a2 -> %hhd",[a1 isEqual:a2]); // Match
    NSLog(@" b1 == b2 -> %hhd",[b1 isEqual:b2]); // Match
    NSLog(@" c1 == c2 -> %hhd",[c1 isEqual:c2]); // Match
    
    NSLog(@" a1 == b1 -> %hhd",[a1 isEqual:b1]); // Doesn't match
    NSLog(@" b1 == c1 -> %hhd",[b1 isEqual:c1]); // Doesn't match
    NSLog(@" c1 == a1 -> %hhd",[c1 isEqual:a1]); // Doesn't match
    

    【讨论】:

    • hash 和具有附加属性的子类有何影响?
    • 你是对的。正如苹果所说“如果两个对象相等,它们必须具有相同的哈希值”。因此,您还应该根据他的属性覆盖 hash 方法以确保它在 isEqual 匹配时匹配。如果子类需要额外的属性,它应该再次覆盖散列方法。一切都取决于您将从哪个用途中使用 isEqual 方法
    【解决方案2】:

    它将在范围内工作......

    如果您实施isEqual:,您还应该实施hash,以便保持平等要求。如果不这样做,并且将自定义对象放入集合中,您可能会得到一些意想不到的结果。

    您的自定义实现也不会考虑子类自定义属性,除非它们覆盖超类实现。这是否是一个问题取决于您如何定义平等。

    在很多情况下,最好不要覆盖 isEqual:,而是添加您自己的自定义比较方法 - 但是,这取决于您希望如何使用相等性。

    基本上,要小心您覆盖的内容,并确保您满足所有相应的相等要求。

    【讨论】:

      猜你喜欢
      • 2020-02-28
      • 1970-01-01
      • 1970-01-01
      • 2010-10-28
      • 1970-01-01
      • 2016-03-24
      • 2017-02-25
      • 2017-12-14
      • 2016-12-28
      相关资源
      最近更新 更多