OC的包装类
“包装类”(Wrapper Class)是指一组用于封装基本数据类型的类。这些包装类提供了一种将基本数据类型转换为对象的方式,从而可以在Objective-C中对其进行操作,与其它编程语言中的类似,用于将基本数据类型(例如int、float、BOOL等)包装成对应的对象。这样做的好处是,在需要使用对象的场景中,可以使用这些包装类来处理基本数据类型。
OC提供了NSValue、NSNumber来封装C语言的基本类型,从而让他们具有面向对象的基本特征。
不是包装类
首先要明确,NSInteger、NSUInteger、GGFLoat不是包装类,他们是基本类型。需要定义整型变量时使用:NSInteger(大致等于long型整数)、NSUInteger(大致等于unsigned long型整数);需要定义浮点型变量时使用:GGFLoat(64位平台——double,32位——float)
NSValue和NSNumber
这两者都是包装类,其中NSValue是NSNumber的父类。
NSValue代表一个更通用的包装类,NSNumber是更具体的包装类。NSNumber主要包括以下3类方法:
- +numberWithXxx: :该类方法直接将特定类型的值包装成NSNumber。
- -initWithXxx: :该实例方法需要先创建一个NSNumber对象,再用一个基本类型的值来初始化NSNumber。
- -xxxValue: :该实例方法返回该NSNumber对象包装的基本类型的值。
代码示例:
#import <Foundation/Foundation.h>
int main(int argc , char * argv[])
{
@autoreleasepool{
//调用类方法将int 类型的值包装成 NSNumber 对象
NSNumber* num = [NSNumber numberWithInt:20];
//调用类方法将double类型的值包装成NSNumber对象
NSNumber* de = [NSNumber numberwithDouble:3.4];
NsLog(@"%d" , [num intValue]);
NSLog(@"%g" , [de doubleValue]);
//先创建NSNumber对象,再调用initwithXxx:方法执行初始化
NSNumber* ch = [[NSNumber alloc] initWithChar:'J'];
//直接输出NSNumber对象,使用%@格式字符串
NSLog(@"%@", ch);
}
return 0;
}
由此可以看出,基本类型变量和包装类对象之间的转换对象关系如图:
处理对象
打印对象和description方法
NSLog()函数不仅可以用于输出基本类型的值,也可以用于输出OC对象(此时,输出的事该对象description方法的返回值)。
description方法是NSObject类的一个实例方法,所有的OC类都是NSObject类的子类,因此所有的OC类都有description方法。该方法是一个“自我描述”的方法,该方法通常用于实现这样一个功能:当程序员直接打印该对象时,系统将会输出该对象的“自我描述”信息,用以告诉外界该对象具有的状态信息。
该方法返回<类:16进制的首地址>,如果用户自定义类能实现“自我描述”的功能,必须重写该方法。重写该方法总是返回该对象所有所需信息组成的字符串,格式如下:
<类名:[实例变量1 = 值1,实例变量2 = 值2,…]>
通过改写description方法,可以实现让系统在打印对象时打印出该对象的“自我描述”信息。实现了对该对象的自我描述。
改写完description方法后,我们输出就可以直接写对象名了,输出的结果就是重写过的description方法中的格式化字符串。
代码示例如下:
接口部分:
#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
- (id) initWithColor:(NSString *)color weight:(double) weight
{
if(self = [super init])
{
self.color = color;
self.weight = weight;
}
return self;
}
//重写父类的decription方法
- (NSString*) description
{
//返回一个字符串(stringWithFormat可生成格式化字符串)
return [NSString stringWithFormat:@"<FKApple [_color = %@, _weight = %g]>", self.color, self.weight];
}
@end
主函数部分:
#import <Foundation/Foundation.h>
#import "FKApple.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
//创建一个FKApple对象,将之赋给a变量
FKApple* a = [[FKApple alloc] initWithColor:@"红色" weight:5.68];
//打印FKApple对象
NSLog(@"%@", a);
}
return 0;
}
==和isEqual方法
OC中测试两个变量是否相等的方式有两个,分别是:== 方法和isEqual方法。
==方法
该方法返回1(真)或0(假)。
当比较类型为基本类型且都是数值型(不一定要求数据类型完全相同)时,比较它们的值,值相等返回真,否则为假。
当比较类型为指针类型时,则要两个指针指向同一个对象,即比较的是它们的地址值,地址值相等返回真,否则返回假。
当使用==的两个类没有继承关系时,编译器会提示警告。
代码示例:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
@autoreleasepool {
int it = 65;
int fl = 65.0f;
NSLog(@"65和65.0f是否相等?%d",(it == fl)); //结果为1 代表为真 两者相等
char ch = 'A';
NSLog(@"65和'A'是否相等?%d",(fl == ch)); //结果为1 代表为真 两者相等
NSString* str1 = @"黄昏好帅";
NSString* str2 = @"黄昏好帅";
NSLog(@"%d",(str1 == str2)); //结果为1 代表为真 两者相等
NSString* str3 = @"约尔战斗力爆表";
NSLog(@"%d",(str2 == str3)); //结果为0 代表为假 两者不相等
NSString* str4 = [NSString stringWithFormat:@"黄昏好帅"];
NSLog(@"str1地址:%p, str4地址:%p", str1, str4);
NSLog(@"%d",(str1 == str4)); //结果为0 代表为假 两者不相等
NSString* str5 = [NSString stringWithFormat:@"黄昏好帅"];
NSLog(@"%d",(str4 == str5)); //结果为0 代表为假 两者不相等
NSString* str6 = [NSString stringWithFormat:@"hello"];
NSString* str7 = [NSString stringWithFormat:@"hello"];
NSLog(@"%d",(str6 == str7)); //结果为1 代表为真 两者相等
}
return 0;
}
isEqual方法
isEqual:方法是NOSbject类提供的一个实例方法,所以所有的指针变量都可以调用该方法来判断是否与其他指针变量相等。该方法判断两个对象相等的标准几乎与 = =方法没有区别,都要求两个指针指向同一个对象。 如果希望采用自定义的的相等标准,要采用重写isEqual:方法来实现。
NSString已经重写了NSObject的isEqual:方法,NSString的isEqual:方法判断两个字符串是否相等的标准是只要两个字符串所包含的字符序列相同,就返回1(真),否则返回0(假)。
下面实现了对isEqual:方法的重写:
接口部分:(定义了一个FKDog空类)
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface FKDog : NSObject
@end
NS_ASSUME_NONNULL_END
实现部分:
#import "FKDog.h"
@implementation FKDog
- (BOOL) isEqual:(id)other
{
return TRUE;
//不进行判断 直接返回YES(即导致FKDog对象与任何对象比较都相等 都会返回YES)
}
@end
主函数部分:
#import <Foundation/Foundation.h>
#import "FKDog.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
FKDog* p = [[FKDog alloc] init];
NSLog(@"FKDog对象是否与NSString对象相等?%d", [p isEqual: [NSString stringWithFormat:@"hello"]]);
}
return 0;
}
运行结果:
因为上面代码对isEqual:方法进行重写时,没有加任何判断,永远返回真,所以会出现FKDog对象和NSString对象相等的荒谬结论。
我们在正确地重写isEqual:方法时,应满足以下条件:
提示: