<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont

简介: 作者:韩俊强总结以往方法: 继承是可以完成对类型的扩充,不仅能添加方法,也可以添加实例变量;/缺点:如果工程中有很多需要扩充类的使用,此时要用子类去完成替换,工作量非常大,还容易出错。
作者:韩俊强
总结以往方法: 继承是可以完成对类型的扩充,不仅能添加方法,也可以添加实例变量;/缺点:如果工程中有很多需要扩充类的使用,此时要用子类去完成替换,工作量非常大,还容易出错。下面通过例子过渡一下进入类的扩展!
==============================================================
 1.例子:通过继承完成类的扩展
Person.h
@interface Person : NSObject
{
   
NSString *_name;
   
NSInteger _age;
   
//添加新实例变量
   
NSString *_sex;
}
- (
void)sayHi;
//给类添加新方法
- (void)sayHello;

Person.m
//这是延展,此时的延展不需要创建.h文件,直接将延展写到类的.m文件中
//建议以后写延展都是用这种方式
//延展方便我们管理一个类的私有方法和实例变量

@interface Person ()
{
   NSString *_hobby; 
}
- (void)dance;
@end
@implementation Person
//延展的实现部分
- (void)dance{
    NSLog(@"-----------跳舞真好) ;  
}
- (void)sayHi{
   NSLog(@"你好 包小姐!");
}
//给类添加新方法
- (
void)sayHello{
   
NSLog(@"Hello 包小姐!");
   
//调用延展里声明的方法
    [
self dance];
}
@end
main.m
//如何为Person这个类添加方法
   
Person *p = [[Person alloc]init];
    [p
sayHi];
    [p sayHello];
    Student *p1 = [[Student alloc]init];
    [p1 study];
    //调用分类的方法 (知道源文件情况)
    [p1 hitPlan];
======================================================
在上题中我们扩展一个Category 类的扩展:
2、使用Category 分类或类目
    主要作用是为没有源代码的类添加方法,禁忌:使用Category 给类添加方法可以,但是不能添加实例变量
  **添加分类的步骤:
   
//1.新建文件 command + n
   
//2.选择Object-c  File模板
   
//3.File栏根据扩展的功能写入文件名
   
//4.中间栏选择Category
   
//5.Class选项写入对那个类的扩充,就写入那个类的类名
   
//6.next之后会自动生成一对“类名 + 扩展名.h”和“类型加扩展名.m”文件
   //7.在.h写入方法声明,在.m中写方法实现
Person+Study.h
//小括号代表某个类的分类
//(分类名)
@interface Person (Study)
{
//    NSString *_color;     error!!!实例变量不能定义到分类中
}
//分类不仅可以添加类方法也可以添加对象方法
//类方法
+ (
void)study;
//对象方法
- (
void)study;
- (
void)sayHi;
@end
Person+Study.m
@implementation Person (Study)
//类方法
+ (
void)study{
   
NSLog(@"学习LOL包小姐");
}
//对象方法
- (
void)study{
   
NSLog(@"学习CF包小姐");
}
- (
void)sayHi{
   
NSLog(@"你好,苹果");
}
@end

Student.h
@interface Student : Person
{
   
NSInteger _number;
}
- (void)study;
@end
//不正式添加分类的方法
@interface Student (hitPlan)
- (void)hitPlan;
@end

Student.m
@implementation Student
- (
void)study{
   
NSLog(@"努力学习包小姐");
}
@end
@implementation Student (hitPlan)
//分类的实现  这种方式只适合能看到源文件的类
- (
void)hitPlan{
   
NSLog(@"打飞机");
}
@end

main.m
 //使用Category 添加的方法,是直接作用到当前那个类上的,可以使用当前类或者当前类创建的对象直接调用方法
   
Person *p2 = [[Person alloc]init];
    [
Person study];
    [p2
study];
   
//如果分类中定义和原始中一样的方法,此时优先选择执行分类中的方法
    [p1 sayHi];

=====================================================
3、 练习:为NSString 添加分类(类方法)
NSString+Say.h
@interface NSString (SayHi)
- (
void)sayHi;
//拼接字符串的方法
- (
NSString *)appendingString : (NSString *)string;
@end
NSString+Say.m
@implementation NSString (SayHi)
- (
void)sayHi{
   
NSLog(@"你好 我是5号");
}
//拼接字符串的方法
- (
NSString *)appendingString : (NSString *)string{
   
return [string stringByAppendingString:@"约嘛?"];
}
@end
main.m
    //为NSString 添加分类
   
NSString *s = [NSString string];
    [s
sayHi];
  
NSString *newString =  [s appendingString:@"罗玉凤"];
   NSLog(@"%@",newString);
======================================================
4、练习: 为NSDate添加一个对象(对象方法)
NSDate+Date.h
@interface NSDate (Date)
+ (
NSDate *)dateWithDateString : (NSString *)dateString;
@end
NSDate+Date.m
@implementation NSDate (Date)
+ (
NSDate *)dateWithDateString : (NSString *)dateString{
   
//日期格式对象
   
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
   
//指定格式
    [formatter
setDateFormat:@"yyyyMMddHHmmss"];
   
NSDate *date1 = [formatter dateFromString:dateString];
   
return [date1 dateByAddingTimeInterval:8 *60 *60];
}
@end
main.m
 //准备时间字符串
   
NSString *dateString = @"20150907160230";
   
NSDate *date = [NSDate dateWithDateString:dateString];
   NSLog(@"%@",date);
  ----------------------------------------------------------------------          
   总结 :  延展和分类的区别
 1.延展中可以添加实例变量,分类中不可以
 2.延展中的方法和实例变量都是私有的,不能直接访问,分类中的方法外界可以访问
 3.延展针对是已知类(因为它的实现只能在这个类的.m文件中写),分类中可以为不知道源文件的类添加方法;
 4.延展中的子类不能继承,而分类中的方法子类可以直接使用
(私有方法下面Dog类会再做例子说明)
======================================================
5、代理模式(Delegate)解题思路:
 协议和代理的使用
 1.定义协议(协议中存放的是代理应该完成的方法)
 2.定义代理实例变量(用来存储在外界设置的代理对象)
 3.在.m文件中让_delegate执行协议中的方法,并且为这些方法设置触发的时机
 4.在其他文件中指定代理对象,对象要遵循协议内容(答应去干活)
 5.代理对象实现协议中的方法(知道怎么去干活)
 6.指定协议方通知代理对象干活(让代理干活)

-----------------------------------------------------------------------------------
 6、****代理设计模式的步骤:
     1.制订协议
     2.找代理,遵循协议
     3.成为代理
     4.执行协议中的方法
     =============制定协议的步骤:==============
     1.Command + n 新建文件
     2.文件名(类名 + delegate) eg: PersonDelegate
     3.中间栏选Protocal
     4.Class 哪个类指定的协议就写那个类
     5.只生成.h文件
     6.谁成为代理就去谁的.m文件写协议中方法实现
例题: 创建一个Dog对象(模拟私有方法)
Dog.h
#import "Girl.h"
@interface Dog : NSObject<</span>GirlDelegate>    //遵循GirlDelegate协议
- (void)eatShit;
@end
Dog.m
#import "Dog_Private.h"
@implementation Dog
- (void)eatShit{
   
_isTrue = YES;
   
if (_isTrue) {
       
//延展中的私有方法
        [
self eatBone
];
       
NSLog(@"躺着吃");
    }
else{
       NSLog(@"哈哈躺着吃啊");
    }
 }
- (void)eatBone{
    NSLog(@"骨头真香啊");
}
@end
- (void)wellDone
{
   
NSLog(@"你去找别人把");
}
- (void)makeMoney
{
   NSLog(@"你把我卖了吧");
Dog_private.h
@interface Dog ()
{
   
BOOL _isTrue;
}
- (
void)eatBone;//吃骨头
@end
main.m
Dog *d = [[Dog alloc]init];
    [d
eatShit];
    [d eatBone];
======================================================
7、协议和代理模式
例题:建立一个女孩找男朋友的征婚启事
Girl.h
#import "GirlDelegate.h"
@interface Girl : NSObject
{
   
//设置一个男朋友的属性
   
//此时这个实例变量必须遵循协议 <协议名称>
   
//遵循协议符号 <协议名称>

   
id <</span>GirlDelegate>_boyFriend;
   
NSString *_name;
}
- (
void)setName : (NSString *)name;
- (
NSString *)name;
//写setter getter方法
- (
void)setBoyFriend : (id<</span>GirlDelegate>)boyFriend;
- (
id<</span>GirlDelegate>)boyFriend;
- (
void)wangShopping;
- (
void)wantHappy;
- (
void)wantFun;
- (
void)wantEating;
@end
Girl.m
@implementation Girl
- (
void)setName: (NSString *)name{
   
_name = name;
}
- (
NSString *)name{
   
return _name;
}

- (
void)setBoyFriend : (id<</span>GirlDelegate>)boyFriend{
   
_boyFriend = boyFriend;
}
- (
id<</span>GirlDelegate>)boyFriend{
   
return _boyFriend;
}

- (
void)wangShopping{
    if ([_boyFriend respondsToSelector:@selector(makeMoney)]) {
          [_boyFriend makeMoney]; 
    }else{
       
NSLog(@"出去卖切糕");
    }
}
- (
void)wantHappy{
   
if ([_boyFriend respondsToSelector:@selector(wellDone)]) {
        [
_boyFriend wellDone
];
    }
else{
       
NSLog(@"换人");
    }
}
- (
void)wantEating{
   
//如果代理没有执行协议中的方法,此时加了这个判断就不会造成crash
   
if ([_boyFriend respondsToSelector:@selector
(cook)]) {
       [
_boyFriend cook];
    }
else{
       
NSLog(@"自己做着吃");
    }
}
- (
void)wantFun{
   
    [
_boyFriend cook];
}
@end
GirlDelegate.h 协议文件
@protocol GirlDelegate <</span>NSObject>
@required
//required 修饰协议的内容是必须实现的
//能挣钱
- (
void)makeMoney;
//能干              
- (
void)wellDone;
@optional
//optional 修饰协议   可选择实现的

//做饭
- (
void)cook;
//幽默
- (
void)humorous;
@end
我们再定义一个接受女孩的一个男孩,男孩遵循协议并在Boy.m实现
Boy.h
#import "GirlDelegate.h"
//一个类要想成为代理必须遵循协议, 协议的位置写在其父类的后面,使用一对尖括号<>
@interface Boy : NSObject<</span>GirlDelegate>
{
   
NSString *_name;
}
- (
void)setName : (NSString *)name;
- (
NSString *)name;
@end
Boy.m
@implementation Boy
- (
void)setName : (NSString *)name{
   
_name = name;
}
- (
NSString *)name{
   
return _name;
}
//实现协议中必须实现的方法
- (
void)makeMoney
{
   
NSLog(@"一百万够不够花");
}
- (
void)wellDone
{
   
NSLog(@"一瓶伟哥够不");
}
//实现协议中可选的方法
- (
void)cook
{
   
NSLog(@"小鸡炖蘑菇");
}
- (
void)humorous
{
   
NSLog(@"你看我长得像不像周润发?");
}
@end
main.m
一天18岁的小樱决定结束自己18年的单身生活
   
Girl *g = [[Girl alloc]init];
    g.
name = @"小樱";
   
//于是它定义一个协议,心想,谁能完成协议,我当他女朋友
   
//此时25岁小军,下决定脱单,看到网上征婚协议
   
//一天后,鼓起勇气,小军看到协议,又摸了摸钱包,一咬牙签了
   
   
Boy *b = [[Boy alloc]init];
    b.
name = @"小军";
   
//签了协议就能成为小樱的男朋友
    g.
boyFriend = b;
   
   
//我想吃购物
    [g
wangShopping];
   
   
//我想幸福
    [g
wantHappy];
   
   
//我想开森
    [g
wantFun];
   
    //由于小军体能下降换男朋友(Dog)了   (和Dog例子调用蓝色部分)
    Dog *d1 = [[Dog alloc]init];
    g.
boyFriend = d1;
    [g
wantHappy];
    [g wangShopping];
欢迎阅读本文,转载分享请注明出处!
目录
相关文章
|
Web App开发 前端开发
|
Web App开发 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
PipeMapRed.waitOutputThreads(): subprocess failed with code X ,这里code X对应的信息如下:error code 1: Operation not perm...
912 0
|
Web App开发 前端开发 Java
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
服务端需在vm arguments一栏下加上    -agentlib:jdwp=transport=dt_socket,server=y,address=8000 并以run模式启动 如果以debug模式启动服务端...
694 0
|
Web App开发 前端开发 Java
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
kafka.common.ConsumerRebalanceFailedException: group_dd-1446432618163-2746a209 can't rebalance after 10 retries  at kafka.
783 0
|
Web App开发 前端开发 Java
|
Web App开发 Java Apache
|
Web App开发 前端开发 大数据
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
数据案例-蓝米手机的精准广告营销 2016-01-25 劲说 背景介绍:假设我是大米手机的数据分析师大傅,今天收到市场运营小旋同学的春节投放需求,在大米平台的DMP投放展示广告,做促销蓝米手机活动,投放预算是100万,同时悄悄告诉我,如果投放ROI超过2,她们市场运营总监设立奖励金额为(n-2)*1万的奖金。
708 0