Objective-C学习笔记——处理对象

打印对象和description

定义与理解

description方法是NSObject类的一个实例方法,所有的Objective-C都是NSObject类的子类,因此,所有的Objective-C对象 都具有description方法。
description方法是一个非常特殊的方法,它是一个“自我描述”方法,该方法通常用于实现这样一个功能:当程序员直接打印该对象时,系统将会输出该对象的“自我描述”功能,用以告诉外界该对象具有的状态信息。
NSObject类提供的description方法总是返回<FKPerson: 16进制的首地址>,这个返回值并不能真正实现“自我描述”的功能,因此,如果用户需要自定义类能实现“自我描述”的功能,必须重写NSObject类的description方法。

大部分时候,重写description方法总是返回该对象所有令人感兴趣的信息所组成的字符串,通常可返回如下格式的字符串:
<类名[实例变量1 = 值1, 实例变量2 = 2,…]>

实例

#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface FKApple : NSObject
@property (nonatomic , copy)NSString* color;
@property (nonatomic , assign)double weight;
-(id) initWithColor: (NSString*) color weight: (double) weight;
@end
NS_ASSUME_NONNULL_END
#import "FKApple.h"
@implementation FKApple
@synthesize  color = _color;
@synthesize  weight = _weight;
-(id) initWithColor:(NSString *)color weight:(double)weight
{
    if (self = [super init])
    {
        self.color = color;
        self.weight = weight;
    }
    return self;
}
-(NSString*) description
{
    return [NSString stringWithFormat:@"<FKApple[_color=%@, _weight=%g]>", self.color, self.weight];
}
@end
#import <Foundation/Foundation.h>
#import "FKApple.h"

int main(int argc , char * argv[])
{
    @autoreleasepool {
        FKApple* a = [[FKApple alloc] initWithColor:@"红色" weight:2.58];
        NSLog(@"%@", a);
    }
}

我们看一下运行结果:
在这里插入图片描述

所以当我们重新写了description方法时,我们想要的结果就出来了,它告诉了我们颜色和重量的内容。

==和isEqual方法

我们都知道==运算符,它在判断两个变量是否相等时,如果两个变量是基本类型的变量,且都是数值型(不一定要求数据类型完全相同),则只要两个变量的值相等,使用 ==判断并返回真。
对于两个指针类型的变量,它们必须指向同一个对象(也就是两个指针变量保存的内存地址相同)时, ==判断才会返回真。当使用 ==比较类型上没有继承关系的两个指针变量时,编译器回提示警告,下面程序示范了使用 ==来判断两种类型变量是否相等的结果。

#import <Foundation/Foundation.h>
#import "FkPerson.h"
int main(int argc , char * argv[])
{
    @autoreleasepool {
        int it = 65;
        float f1 = 65.0f;
        NSLog(@"65和65.0f是否相等?:%d", (it == f1));//将输出1代表真
        char ch = 'A';
        NSLog(@"65和'A'是否相等? %d",(it == ch));//将输出1代表真
        NSString* str1 = [NSString stringWithFormat:@"hello"];
        NSString* str2 = @"hello";
        NSLog(@"str1和str2是否相等?%d", (str1 == str2));
        NSLog(@"str1是否isEqualstr2?%d",[str1 isEqual: str2]);
        
    }
}

运行结果如图所示:
在这里插入图片描述

我们可以看到,65、65.0f和’A’相等。但对于str1和str2,因为它们都是指针类型变量,它们分别指向两个通过NSString的静态方法创建出来的NSString对象,因此str1和str2两个变量不相等。

常量池

==常量池保证相同的字符串直接量只有一个,不会产生多个副本。==我们使用NSString stringWithFormat:类方法创建的字符串对象是运行时创建出来的,它被保存在运行时内存区(即堆内存),不会放入常量池中。

代码展示:

#import <Foundation/Foundation.h>
#import "FkPerson.h"
int main(int argc , char * argv[])
{
    @autoreleasepool {
        //s1、s2直接指向常量池中的"疯狂iOS"
        NSString* s1 = @"疯狂iOS";
        NSString* s2 = @"疯狂iOS";
        //看到s1、s2两个指针保存的地址完全相等
        NSLog(@"s1地址:%p, s2的地址:%p", s1, s2);
        //所以下面的程序输出1代表真
        NSLog(@"s1与s2是否相等: %d", (s1 == s2));
        //让s3指向新生成的对象
        NSString* s3 = [NSString stringWithFormat:@"疯狂iOS"];
        //输出s3指针变量中保存的地址值与s1、s2并不相同
        NSLog(@"s3地址:%p", s3);
        //所以下面的程序输出0代表假
        NSLog(@"s1与s3是否相等: %d", (s1 == s3));
        
    }
}

我们可以看到NSString stringWithFormat:类方法创建的字符串对象是运行时创建出来的,它被保存在运行时内存区(即堆内存),不会放入常量池中,所以它和s1、s2虽然是同样的一句话可是地址不一样用==判断结果为假。

重写isEqual: 方法

如果我们想让isEqual:方法来实现自定义标准,那么我们就需要在实现部分重写isEqual:方法。

虽然NSString已经重写了最开始NSObject的isEqual:方法:NSString判断两个字符串的标准是:只要两个字符串所包含的字符序列相同,则返回真,否则返回假。
代码如下:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface FKUser : NSObject
@property (nonatomic , copy) NSString* name;
@property (nonatomic , copy) NSString* idStr;
-(id) initWithName: (NSString*) name
    idStr: (NSString*) idStr;
@end

NS_ASSUME_NONNULL_END

#import "FKUser.h"

@implementation FKUser
@synthesize name = _name;
@synthesize idStr = _idStr;
-(id) initWithName:(NSString *)name idStr:(NSString *)idStr
{
    if (self = [super init])
    {
        self.name = name;
        self.idStr = idStr;
    }
    return self;
}
-(BOOL) isEqual:(id)other
{
    if (self == other)
    {
        return YES;
    }
    if (other != nil && [other isMemberOfClass:FKUser.class])
    {
        FKUser* target = (FKUser*)other;
        return [self.idStr isEqual:target.idStr];
    }
    return NO;
}
@end
#import <Foundation/Foundation.h>
#import "FKUser.h"

int main(int argc , char * argv[])
{
    @autoreleasepool {
        FKUser* p1 = [[FKUser alloc] initWithName:@"孙悟空" idStr:@"12343433433"];
        FKUser* p2 = [[FKUser alloc] initWithName:@"孙行者" idStr:@"12343433433"];
        FKUser* p3 = [[FKUser alloc] initWithName:@"孙悟饭" idStr:@"99933433"];
        NSLog(@"p1和p2是否相等?%d", [p1 isEqual: p2]);
        NSLog(@"p2和p3是否相等?%d", [p2 isEqual: p3]);
    }
}

运行结果如图所示:
在这里插入图片描述
我们可以看到,p1和p2的地址相等,所以[p1 isEqual : p2]返回值为1,而又因为p2和p3的地址不相等,所以[p2 isEqual : p3]返回值为0。重新了isEqula:方法后,我们就可以比较两个对象是否相等。

正确重写isEqual:方法要满足的条件

  1. 自反性:对任意x,[x isEqual: x]一定返回真。
  2. 对称性:对任意x和y,如果[x isEqual: y]返回真,则[y isEqual: x]一定返回真。
  3. 传递性:对任意x、y、z,如果[x isEqual: y]返回值,[y isEqual: x]返回真,则[x isEqual: z]一定返回真。
  4. 一致性:对任意x和y,如果对象中用于等价比较的关键消息没有改变,那么无论调用[x isEqual: y]多少次,返回的结果应保持一致,要么一直是真,要么一直是假。
  5. 对任何不适nil的x,[x isEqual : nil]一定返回假。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值