黑马程序员_分类协议代码块
来源:互联网 发布:名片录入软件 编辑:程序博客网 时间:2024/06/06 05:42
分类
1.category的声明
category即分类,也有叫类别,类目。分类为类的拓展提供了另一种方法。分类可以在不改变原有类的基础上,增加类的方法或者覆写已有类的方法。
Seed.h
@interface Seed : NSObject@property int count;@property NSString *name;- (void)print;@end
Seed.m
@implementation Seed- (void)print{ NSLog(@"count = %d",_count); NSLog(@"name = %@",_name);}@end
Seed+fruite.h
@interface Seed (fruite)- (void)print;- (void)fun;@end
Seed+fruite.m
@implementation Seed (fruite)- (void)print{ NSLog(@"fruite is loading");}- (void)fun{ NSLog(@"fruite is fun");}@end
main.m
int main(int argc, const char * argv[]){ Seed *s = [Seed new]; [s print]; [s fun]; return 0;}
运行结果:
2014-06-05 18:07:43.035 cate[1306:303] fruite is loading2014-06-05 18:07:43.037 cate[1306:303] fruite is funProgram ended with exit code: 0
OC中不提倡用分类覆写原有类的方法,所以在编译的时候会有警告,但是不影响程序的运行。分类一般拓充原有类中没有的方法。
2.分类的拓充方法
OC在使用分类扩充方法时,如果有原有类中没有的方法,分类不改变原有类编译运行。如果分类中覆写了原有类中的方法,分类会替代该类中的方法。如果子类的分类覆写了父类中的方法,那么父类的方法就不能使用。
Person.h
@interface Person : NSObject{ int _num; NSString *_name;}@property int num;@property NSString *name;- (void)test;- (void)study;@end
Person.m
@implementation Person- (void)test{ NSLog(@"Person is test");}- (void)study{ NSLog(@"Person is study");}@end
Student.h
@interface Student : Person@end
Student.m
@implementation Student- (void)test{ NSLog(@"Student is test");}@end
Person+test.h
@interface Person (test)- (void)print;@end
Person+test.m
@implementation Person (test)- (void)print{ NSLog(@"num = %d",_num); NSLog(@"name = %@",_name);}@end
Student+study.h
@interface Student (study)@end
Student+study.m
@implementation Student (study)- (void)study{ NSLog(@"Student+study is study");}- (void)test{ NSLog(@"Student+study is test");}@end
Student+test.h
@interface Student (test)- (void)test;- (void)study;- (void)print;@end
Student+test.m
@implementation Student (test)- (void)test{ NSLog(@"Student+test is test");}- (void)study{ NSLog(@"Student+study is study");}- (void)print{ NSLog(@"name = %@",_name); NSLog(@"num = %d",_num);}@end
main.m
int main(int argc, const char * argv[]){ Person *p = [[Person alloc] init]; [p test]; [p study]; p.name = @"lsmseed"; p.num = 10; [p print]; Student *s = [[Student alloc] init]; [s test]; [s study]; [s print]; s.name = @"buster"; s.num = 20; [s print]; return 0;}运行结果:
2014-06-05 18:42:59.330 rer[1552:303] Person is test2014-06-05 18:42:59.335 rer[1552:303] Person is study2014-06-05 18:42:59.337 rer[1552:303] num = 102014-06-05 18:42:59.338 rer[1552:303] name = lsmseed2014-06-05 18:42:59.339 rer[1552:303] Student+test is test2014-06-05 18:42:59.340 rer[1552:303] Student+study is study2014-06-05 18:42:59.341 rer[1552:303] name = (null)2014-06-05 18:42:59.343 rer[1552:303] num = 02014-06-05 18:42:59.345 rer[1552:303] name = buster2014-06-05 18:42:59.346 rer[1552:303] num = 20Program ended with exit code: 0
由于分类覆写了原有类中的方法,因此,类在调用方法时优先会在分类中寻找对应的方法,如果没有会依次在子类,在父类中找到对应的方法。如果分类较多,最后编译的分类方法优先级高。同时,分类还可以访问原有类中的成员变量。
3.分类的使用注意
- 分类不提倡覆写原有类中的同名方法
- 分类不能增加原有类中的成员变量
- 分类方法的调用优先级是参与编译的顺序:最后编译的优先调用。
协议
1.协议的声明格式
OC中的协议类似java中的接口,只不过OC中的协议只有方法的声明,不能定义变量。一般协议的声明方式如下:
@protocol Myprotocol <NSObject>- (void)fun;@required- (void)print;@optional- (void)test;- (void)test2;@end
@protocol是声明协议的关键字,Myprotocol是协议名称。一般协议中声明的方法默认都是必须实现的,也就是@required修饰的方法声明。@optional是可选实现的方法。虽然@required是必须实现的方法,但是即便没有实现编译器也不会报错,只会报警告。
2.基协议
基协议就是最基本的协议,也就是NSObject协议。这个协议中声明了许多OC框架中基本的方法。一般在新定义的协议中都会遵守基协议。
@protocol Myprotocol <NSObject>
3.协议限制对象
在创建对象时,可以指定对象需要遵守的协议。这样协议就规定了创建出的对象必须实现的方法。
Myprotocol.h
@protocol Myprotocol <NSObject>@required- (void)print;- (void)fun;@end
Car.h
#import "Myprotocol.h"@interface Car : NSObject<Myprotocol>@end
Car.m
@implementation Car- (void)print{ NSLog(@"seed");}- (void)fun{ NSLog(@"fun");}@end
Red.h
@interface Red : NSObject@end
Red.m
@implementation Red- (void)print{ NSLog(@"Red is print");}- (void)fun{ NSLog(@"Red is fun");}- (void)test{ NSLog(@"red is test");}- (void)test1{ NSLog(@"red is test1");}@end
main.m
#import "Myprotocol.h"#import "Car.h"#import "Red.h"int main(int argc, const char * argv[]){ NSObject<Myprotocol> *obj = [[Car alloc] init]; [obj print]; [obj fun]; NSObject<Myprotocol> *obj1 = [[Red alloc] init]; [obj1 print]; return 0;}
运行结果:
2014-06-06 18:25:04.959 dd[1080:303] seed2014-06-06 18:25:04.962 dd[1080:303] fun2014-06-06 18:25:04.963 dd[1080:303] Red is printProgram ended with exit code: 0
定义一个限定遵守制定协议的对象,其对象本身就是一个已遵守该协议的一个引用。只要创建一个已经遵守这个协议的对象并赋值就可以了。虽然也可以传入未实现该协议且已实现该协议方法的对象,但是,编译时会出警告。协议限定对象也可以限定类中的成员。
Study.h
@protocol Study <NSObject>- (void)work;- (void)hard;@end
Work.h
@protocol Work <NSObject>- (void)work1;@end
Person.h
#import "Work.h"@interface Person : NSObject<Work>@property int num;@property NSString *name;- (void)work1;@end
Person.m
@implementation Person- (void)work1{ NSLog(@"Person is work1");}@end
Student.h
#import "Study.h"@interface Student : Person<Study>- (void)hard;- (void)work;@end
Student.m
@implementation Student- (void)hard{ NSLog(@"Student is hard");}- (void)work{ NSLog(@"Student is work");}@end
School.h
#import "Study.h"#import "Student.h"#import "Person.h"#import "work.h"@interface School : NSObject@property (nonatomic,strong) Student<Study> *s;@property (nonatomic,strong) id<Work> p;@end
School.m
@implementation School@end
main.m
#import "School.h"int main(int argc, const char * argv[]){ School *sc = [[School alloc] init]; sc.s = [[Student alloc] init]; sc.p = [[Person alloc] init]; [sc.s hard]; [sc.p work1]; return 0;}
运行结果:
2014-06-06 18:54:56.628 sd[1243:303] Student is hard2014-06-06 18:54:56.634 sd[1243:303] Person is work1Program ended with exit code: 0
使用property修饰的成员也可以被协议限定,这样自动生成的方法,也要接受遵守协议地对象作为成员。
4.协议提前声明
为了提高编译效率,有时在遵守协议地类中可以不用先导入协议地头文件,可以使用@protocol来先声明要遵守地协议。
@protocol Study;@interface Student : Person<Study>- (void)hard;- (void)work;@end
如果要实现协议的方法那就要在实现的文件中导入头文件。
#import "Study.h"@implementation Student- (void)hard{ NSLog(@"Student is hard");}- (void)work{ NSLog(@"Student is work");}@end
5.协议遵守协议
声明一个协议后还可以让这个协议继续遵守另一个协议,这样这个协议的方法就被进一步扩充一次。
@protocol Work;@protocol Study <Work>- (void)work;- (void)hard;@end
一个协议遵守另一个协议,这样该协议就拥有了另一个协议的方法声明。在方法拓展上,可以将一个大家普遍使用的协议做成基本协议,然后再衍生出一些子协议。
6.代理模式
代理模式是一种程序的设计模式,简单来说代理就是找人帮忙做自己不能直接完成的事。有了代理,一切事务都可以交给他来完成,不用自己亲自动手。
Dele.h
@protocol Dele <NSObject>- (void)catch;- (void)throw;@end
Person.h
@class Dog;@protocol Dele;@interface Person : NSObject@property NSString *name;@property (nonatomic,strong) Dog<Dele> *d;- (void)test;@end
Person.m
#import "Dog.h"#import "Dele.h"@implementation Person- (void)test{ [_d catch]; [_d throw];}@end
Dog.h
@protocol Dele;@interface Dog : NSObject <Dele>@end
Dog.m
#import "Dele.h"@implementation Dog- (void)catch{ NSLog(@"Dog is catch");}- (void)throw{ NSLog(@"Dog is throw");}@end
main.m
#import "Dele.h"#import "Person.h"#import "Dog.h"int main(int argc, const char * argv[]){ Person *p = [[Person alloc] init]; p.d = [[Dog alloc] init]; [p test]; return 0;}
运行结果:
2014-06-07 09:09:00.007 dele[445:303] Dog is catch2014-06-07 09:09:00.010 dele[445:303] Dog is throwProgram ended with exit code: 0
创建一个Person对象,再在对象中创建一个代理属性,这个属性接收一个遵守协议的对象后就可以代替类拓充一些方法。Person对象中拥有d属性且d属性遵守Dele协议,这样d属性就必须有Dele中的方法实现。因此,Person中的test方法,是由代理d间接实现的。
block
1.block的定义
OC中的block和C中的函数很像,都能封装一段具有特定功能的一段代码。但是,block的定义和使用比函数更加灵活。block在程序中定义的位置较灵活,OC建议多用block。
#import <Foundation/Foundation.h>int main(int argc, const char * argv[]){ void (^myblock)() = ^{ NSLog(@"seed"); }; myblock(); int (^sum)(int,int); sum = ^(int a,int b){ return a + b; }; NSLog(@"sum = %d",sum(10,20)); typedef NSString *(^print)(NSString *); print lsm; lsm = ^(NSString *name){ return name; }; NSLog(@"%@",lsm(@"lsmseed")); return 0;}
运行结果:
2014-06-07 09:53:55.881 b1[608:303] seed2014-06-07 09:53:55.894 b1[608:303] sum = 302014-06-07 09:53:55.896 b1[608:303] lsmseedProgram ended with exit code: 0
block的定义特点就是在block名称前加^号。block的定义可以带参数也可以不带参数。不带参数的定义在给block赋值时一定要保留小口号,也就是void (^block)(),否则编译报错。带参的block要注意block默认的返回值是int型。
2.block的应用
block的应用主要是在IOS开发中的GCD中,它可以方便系统的接口调用。就block本身来说它和函数指针几乎一模一样。但是函数需要先定义再使用,而block可以直接调用代码块使用。
3.block变量值的修改
block内部可以访问外部的变量,但是不能修改外部变量。如果想修改block外部的变量要加关键字_block。
#import <Foundation/Foundation.h>int main(int argc, const char * argv[]){ __block int a = 10; void (^myblock)() = ^{ NSLog(@"a = %d",a); a += 10; NSLog(@"a = %d",a); }; myblock(a); return 0;}
运行结果:
2014-06-07 10:25:06.385 b1[645:303] a = 102014-06-07 10:25:06.388 b1[645:303] a = 20Program ended with exit code: 0
----------------------ASP.Net+Unity开发、.Net培训、期待与您交流!----------------------
- 黑马程序员_分类协议代码块
- 黑马程序员_代码块
- 黑马程序员_代码块
- 黑马程序员_静态代码块
- 黑马程序员_静态代码块
- 黑马程序员_笔迹八_关于代码块
- 黑马程序员_分类
- 黑马程序员--代码块
- 黑马程序员_构造函数与构造代码块
- 黑马程序员_关于java中代码块的问题
- 黑马程序员_工具使用03_Xcode自定义代码块
- 黑马程序员_对象,构造函数以及构造代码块
- 黑马程序员_同步代码块(二)
- 黑马程序员------OC block(代码块)和protocol(协议)
- 黑马程序员-@protocol协议代理与block代码块
- 黑马程序员_静态代码块、构造代码块、构造函数
- 【黑马程序员】分类与协议
- 黑马程序员 静态代码块
- Spring 3.2 源码解析 -- XML bean 元素到 BeanDefinition 解析过程
- 小明陪你编游戏系列(四)GDI+实现双缓冲
- 黑马程序员_封装继承多态
- 黑马程序员_内存管理与ARC原理
- 01 计算机系统漫游
- 黑马程序员_分类协议代码块
- Quartz中扩展MethodInvokingJobDetailFactoryBean实现对任务调度的拦截
- linux 替当前目录加权限
- 基于Spring MVC的简单HelloWorld实例
- [Linux]Fedora17/18安装Ruby1.8 和 Redmine 2.2
- nose配合NoteUNit生成XML文件(命令行+脚本)
- 黑马程序员_Foundation框架
- SetCursor
- iOS7 edgesForExtendedLayout