黑马程序员——入学Blog08----分类
来源:互联网 发布:21端口入侵工具 编辑:程序博客网 时间:2024/04/27 18:21
-----------android培训、java培训、iOS培训、.Net培训、期待与您交流!------------
在介绍分类作用是什么之前,先看一下NSObject类的声明:
@interface NSObject <NSObject> { Classisa;}+ (void)load;+ (void)initialize;- (id)init;+ (id)new;+ (id)allocWithZone:(NSZone *)zone;+ (id)alloc;- (void)dealloc;- (void)finalize;- (id)copy;- (id)mutableCopy;+ (id)copyWithZone:(NSZone *)zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE;+ (id)mutableCopyWithZone:(NSZone *)zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE;+ (Class)superclass;+ (Class)class;+ (BOOL)instancesRespondToSelector:(SEL)aSelector;+ (BOOL)conformsToProtocol:(Protocol *)protocol;- (IMP)methodForSelector:(SEL)aSelector;+ (IMP)instanceMethodForSelector:(SEL)aSelector;- (void)doesNotRecognizeSelector:(SEL)aSelector;- (id)forwardingTargetForSelector:(SEL)aSelector NS_AVAILABLE(10_5, 2_0);- (void)forwardInvocation:(NSInvocation *)anInvocation;- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector;- (BOOL)allowsWeakReference NS_UNAVAILABLE;- (BOOL)retainWeakReference NS_UNAVAILABLE;+ (NSString *)description;+ (BOOL)isSubclassOfClass:(Class)aClass;+ (BOOL)resolveClassMethod:(SEL)sel NS_AVAILABLE(10_5, 2_0);+ (BOOL)resolveInstanceMethod:(SEL)sel NS_AVAILABLE(10_5, 2_0);@end@interface NSObject (NSCoderMethods) // < 1 >+ (NSInteger)version;+ (void)setVersion:(NSInteger)aVersion;- (Class)classForCoder;- (id)replacementObjectForCoder:(NSCoder *)aCoder;- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder NS_REPLACES_RECEIVER;@end
// main.m#import <Foundation/Foundation.h>#import "NSString+WDL.h"int main(int argc, const char * argv[]){ @autoreleasepool { NSLog(@"version = %ld",[NSObject version]); } return 0;}运行结果:
虽然在NSObject中没有version这个类方法,但是因为有< 1 >处的代码,NSObject就能调用version方法了,< 1 >处的写法就是分类。分类是指按照种类、等级或性质分别归类。分类的作用大致有以下3点:
1.通过分类可以使类的整体结构变得模块化,更加清晰
2.多人开发同一个类的情况下,使用分类可以避免文件更改的冲突
3.扩展某个类的功能以满足需求,比如NSString类,可以通过分类扩展逆序输出字符串等方法。
分类使用上需要注意的地方
1.分类只能用来增加方法,不能增加成员变量
2.分类方法的实现中可以访问原来类中声明的成员变量
3.分类可以重新实现原来类中的方法,但是会覆盖原来的方法,导致原来的方法无法再使用,所以建议不要重新实现
4.方法调用的优先级: 分类(后编译的优先) > 原来类 > 父类
//// main.m#import <Foundation/Foundation.h>#import "Person.h"#import "Person+Life.h"#import "Person+Job.h"int main(int argc, const char * argv[]){ @autoreleasepool { Person *p = [[Person alloc] init]; // 原来类与两个分类都有breath,观察会调用哪个 [p breath]; // 生活分类的两个方法 [p eat]; [p sleep]; // 工作分类的两个方法 访问了原来类的成员变量 [p doCoder]; [p searchData]; } return 0;}
//// Person.h#import <Foundation/Foundation.h>@interface Person : NSObject@property (nonatomic,assign) int age;// 呼吸- (void) breath;@end
//// Person.m#import "Person.h"@implementation Person// 呼吸- (void) breath{ NSLog(@"一呼一吸");}@end
//// Person+Life.h#import "Person.h"@interface Person (Life)// 吃饭- (void) eat;// 睡觉- (void) sleep;// 呼吸- (void) breath;@end
//// Person+Life.m#import "Person+Life.h"@implementation Person (Life)// 吃饭- (void) eat{ NSLog(@"吃饭");}// 睡觉- (void) sleep{ NSLog(@"睡觉");}// 呼吸- (void) breath{ NSLog(@"生活需要呼吸");}@end
//// Person+Job.h#import "Person.h"@interface Person (Job)// 敲代码- (void) doCoder;// 找资料- (void) searchData;// 呼吸- (void) breath;@end
//// Person+Job.m#import "Person+Job.h"@implementation Person (Job)// 敲代码- (void) doCoder{ NSLog(@"敲代码"); [self setAge:24]; // 设置年龄}// 找资料- (void) searchData{ NSLog(@"找资料"); NSLog(@"这个人多少岁:%d",[self age]);}// 呼吸- (void) breath{ NSLog(@"工作需要呼吸");}@end
运行结果:
看文件编译的先后
所以breath方法调用的是Life分类中的
最后的打印输出证明了分类方法可以直接访问原来类的成员变量
下面使用分类来扩展类NSString
// main.m#import <Foundation/Foundation.h>#import "Person.h"#import "Person+Life.h"#import "Person+Job.h"#import "NSString+Change.h"int main(int argc, const char * argv[]){ @autoreleasepool { NSString *str = [NSString getReverseString:@"Welcome to beijing"]; NSLog(@"str逆序输出为:%@",str); } return 0;}
// NSString+Change.h#import <Foundation/Foundation.h>@interface NSString (Change)// OC字符串逆序输出+(NSString *)getReverseString:(NSString *)str;@end
//// NSString+Change.m#import "NSString+Change.h"@implementation NSString (Change)// OC字符串逆序输出+(NSString *)getReverseString:(NSString *)str{ NSMutableString *mstr = [NSMutableString stringWithString:str]; for (int i = 0; i < str.length / 2; i++) { // 声明两个NSRange变量,保存前后两边的一个字符 NSRange range1 = NSMakeRange(i, 1); NSRange range2 = NSMakeRange(str.length - i - 1 ,1); // 从左到右,依次取出字符串中的每个字符 NSString *subStr1 = [str substringWithRange:range1]; // 从右到左,依次取出字符串中的每个字符 NSString *subStr2 = [str substringWithRange:range2]; // 交换前后两个字符 [mstr replaceCharactersInRange:range1 withString:subStr2]; [mstr replaceCharactersInRange:range2 withString:subStr1]; } return [NSString stringWithFormat:@"%@",mstr];}@end
运行结果:
分析:因为没有访问成员变量,所以写成了类方法,因为是依次从左与从右取出一个字符,然后进行交换,所以只要做字符串长度的一半的次数就好了
0 0
- 黑马程序员——入学Blog08----分类
- 黑马程序员——入学Blog07----@property
- 黑马程序员 —入学笔记《基础知识1》
- 黑马程序员—入学黑马前的内心挣扎。。。。。
- 黑马程序员入学篇——(3)static 关键字
- 黑马程序员入学篇——(4)toString
- 黑马程序员入学篇——(8)还是线程
- 黑马程序员入学篇——(9)关于oop
- 黑马程序员入学篇——(10)反射
- 黑马程序员入学篇——(11)反射2
- 黑马程序员入学篇——(14)java 注解
- 黑马程序员入学Java知识——精华总结
- 黑马程序员——入学Blog01----面向对象(上)
- 黑马程序员——入学Blog02----面向对象(下)
- 黑马程序员——入学Blog04----OC的构造方法
- 黑马程序员——入学Blog06----内存管理
- 黑马程序员——入学Blog09----OC的Block
- 黑马程序员-入学经典
- 进制间的相互转换
- gitlab搭建问题总结
- 经典SQL语句大全
- [C++]LeetCode: 110 Spiral Matrix (螺旋输出矩阵元素)
- boost::log库,示例代码
- 黑马程序员——入学Blog08----分类
- 对listView的一些学习经验
- 启动另外的一个应用程序的Activity(三种方式)
- Uiautomator学习笔记
- -字朋友-
- IOS ARC跟block那点事
- 无法打开登录所请求的数据库,登录失败
- Intent和PendingIntent的区别
- object c 多参数函数解析