黑马程序员_分类协议代码块

来源:互联网 发布:名片录入软件 编辑:程序博客网 时间:2024/06/06 05:42
----------------------ASP.Net+Unity开发.Net培训、期待与您交流!----------------------

分类

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培训、期待与您交流!----------------------


0 0
原创粉丝点击