zoukankan      html  css  js  c++  java
  • Objective-C——判断对象等同性

    无论我们使用什么语言,总是会出现需要判断两个对象是否相等的情况,OC当然也不例外。首先看一段代码:

            NSString *str1 = [[NSString alloc] initWithCString:"equal" encoding:NSUTF8StringEncoding];
            NSString *str2 = @"equal";
            if(str1 == str2)
            {
                NSLog(@"equal");
            }

    很明显,在我们开来,str1和str2是“相等的”。但是事实上equal是不会被打印的。这是因为如果我们直接比较两个对象是否相等,实际上比较的是两个对象的指针是否相等。

    上述代码中str1和str2是分别指向两块不同的内存的,所以肯定不会像等了。

    我们稍微修改一下代码再看看:

            NSString *str1 = [[NSString alloc] initWithCString:"equal" encoding:NSUTF8StringEncoding];
            NSString *str2 = @"equal";
            if([str1 isEqual:str2])
            {
                NSLog(@"equal");
            }

    注意看加粗语句,我们改用NSObject提供的isEqual方法比较,发现"equal"被打印了出来。因为isEqual在NSString 内部被实现的时候比较的是真正的字符串是否相等!

    对象等同性实现

    看过上面例子后,现在我们自己创建一个类来进一步说明等同性

    #import <Foundation/Foundation.h>
    
    @interface EqualObject : NSObject
    
    @property(nonatomic ,strong)NSString *name;
    
    @end
    
    
    #import "EqualObject.h"
    
    @implementation EqualObject
    
    
    
    @end

    定义了一个EqualObject类,有一个name属性。

    现在我们创建两个对象来比较一下:

     EqualObject *object1 = [EqualObject new];
     EqualObject *object2 = [EqualObject new];
            
     if([object1 isEqual:object2])
     {
            NSLog(@"equal");
     }

    发现代码运行结束并没有输出"equal",原因就在于isEqual方法是需要我们自己实现的。NSObject的isEqual:方法默认是比较两个对象指向的地址是否相等,这里开辟了两个对象肯定不想等了。

    现在我们添加isEqual:方法的实现:

    -(BOOL)isEqual:(id)object
    {
        if([self class] == [object class])
        {
            if(![self.name isEqual:[(EqualObject *)object name]])
            {
                return NO;
            }
            return YES;
        }
        else
        {
            return [super isEqual:object];
        }
    }

    这里稍微解释一下,为什么两个对象不同类就调用父类的isEqual:这是因为,有的时候我们是可以让子类等于父类的,我们只需要关注属性是否相同时可以这样写,如果不需要也可以不在父类处理那么久默认不相等了。

    现在我们不对name进行赋值操作依然是没有值打印出来的。

    修改客户端代码:

            EqualObject *object1 = [EqualObject new];
            EqualObject *object2 = [EqualObject new];
            object1.name = @"xiaoming";
            object2.name = @"xiaoming";
            
            if([object1 isEqual:object2])
            {
                NSLog(@"equal");
            }

    发现这时候在运行就已经相等了。

    为类定制等同性方法

    我们可以看到NSString除了可以用isEqual比较是否相等意外,还可以使用isEqualToString来比较!这是专为NSString类定制的等同性方法,提供这样的方法就可以很明确我们实现了该对象的isEqual方法。

    下面为EqualObject提供定制的等同性方法,并修改isEqual:方法

    - (BOOL)isEqualToEqualObject:(EqualObject *)object
    {
        if(self == object)
            return YES;
        if(![self.name isEqualToString:object.name])
            return NO;
        return YES;
    }
    
    - (BOOL)isEqual:(id)object
    {
        if([self class] == [object class])
        {
            return [self isEqualToEqualObject:object];
        }
        else
        {
            return [super isEqual:object];
        }
    }

    然后客户端修改

            if([object1 isEqualToEqualObject:object2])
            {
                NSLog(@"equal");
            }

    很顺利的"equal"了...

    对象hash码

    每一个OC对象内部都是有一个hash码的,当对象存入集合中(Array,Set,HashTable等),那么他们的hash码会被当做键来决定他们该放入哪一个集合中。

    首先我们先看一下集合内部是如何存储的

    hashCode subCollection
    code1 value1,value2,value3,value4
    code2 value5,value6
    code3 value7
    code4 value8,value9,value10

    集合的内部并不像我们所想的那样,是一个hash表,它将插入的对象根据hashCode来决定放入哪一个子集合。如果要删除或者比较集合内元素,它首先根据hashCode找到子集合,然后跟子集合的每个元素比较。

    所以如果我们的对象的hashCode如果都相同,那么就会出现严重的效率问题,

    理论上来说,我们确定等同性的两个对象的hash应该是相同的而不等的两个对象hash也应该不等,这样在存入hashTable之类的集合时,就 会避免相同对象的重复添加,比如我们两个对象hash相等,但实际对象不等,那么添加的时候就会被添加到同一subCollection下面。

    所以为了避免这种情况,我们尽量自己实现一种避免重复的方式,

    这里提供一种,添加一个新属性age,hash实现如下:

    - (NSUInteger)hash
    {
        NSUInteger nameHash = [_name hash];
        NSUInteger ageHash = _age;
        return nameHash ^ ageHash;
    }

    集合中的对象等同性

    我们对NSArray调用isEqual方法,它会对集合里的每个对象和另一个集合相同位置的对象进行isEqual:操作,只有全部相等,两个集合才相等。

    这里说一下,集合里面最后添加都是不可变元素,如果是可变性元素会出现不法控制的情况。

    比如我们往NSSet里面添加两个NSMutableArray,一开始两个array不等,那么set中就有两个元素。

    然后修改一个array使两个相等,这是set中就会有两个相等的元素存在!

  • 相关阅读:
    Springboot配置异常错误页
    Springboot进行hibernate-vidator数据验证
    Springboot模拟https安全访问(使用Java提供的keytool命令生成证书)
    Springboot的项目如何打成war包
    Springboot的开发环境(dev)、测试环境(beta)和生产环境(product)打包部署
    使用Maven构建的Springboot父子工程的项目打包部署
    Springboot整合Spring的.xm配置文件
    Springboot使用MessageSource读取资源文件
    Springboot使用内置对象HttpServletRequest、HttpServletResponse
    Springboot的控制层结合@PathVariable的使用
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/5068064.html
Copyright © 2011-2022 走看看