天天看點

OC學習日記012(二)類目、延展類目、延展

類目、延展

OC學習日記012(二)類目、延展類目、延展

前言

類目跟延展都是為了為現有的類去擴充新的方法而存在的,因為我們程式的開發要符合我們之前所說的開閉原則(對擴充開放,對修改關閉),而類目主要為了去為我們的類去擴充共有的方法,延展是為了去擴充私有的方法。

類目:

定義:

為現有工程中的類和系統類添加新的方法
           

作用:

在類目中添加新的方法及屬性和在原類中添加方法和屬性是一樣的,都能夠被類和類的子類調用。
在類目中為原類添加新的方法和屬性
           

類目的使用場景

1.類包含了很多個方法實作,而這些方法需要不同團隊成員來實作
 2.當你在使用基礎類庫中的類時,你不想繼承這些類而指向添加一些方法時
           

使用類目時的時候需要注意的問題

1.類目可以通路原始類的執行個體變量,但不能添加執行個體變量,如果添加執行個體變量,那就通過繼承建立子類實作。
 2.類目可以重載原始類的方法,但不推薦這麼做,這樣會覆寫掉原始類的方法,如果确實要重載,那就通過繼承建立子類來實作。
 3.和普通接口有所差別的是,在類目的實作檔案中的執行個體方法隻要你不去調用它你可以不用實作所有聲明的所有方法
           

以下是為類添加類目的例子:

(一般在原有的檔案下方寫或者建立一個類目檔案進行書寫,并表明是哪個類的類目。)

OC學習日記012(二)類目、延展類目、延展

以下是一個Tool類的原始類的接口檔案與方法檔案:

Tool.h

//原始類方法
@interface Tool : NSObject
{
    NSString *_name;
}
@property (nonatomic,strong)NSString *property1;
-(void)function1;
@end
           

Tool.m

@implementation Tool
-(void)function1{
    NSLog(@"I am funtion1");
}
@end
           

Tool(Category部分).h

@interface Tool (ToolCategory)
//{
//  類目中不能添加執行個體變量
    //NSString *_adas;
//}
//-(void)function1;//不推薦重載原始類的方法!
-(void)function2;
@end
           

Tool(Category部分).m

@implementation Tool (ToolCategory)

//-(void)function1{
//    
//    NSLog(@"我是類目中的function1");
//}
-(void)function2{
    NSLog(@"%@",_name);
    NSLog(@"I am function2");
    NSLog(@"%@",self.property2);
}
           

外置類目檔案:(Tool+ToolCategory.h)

@interface Tool (ToolCategory)
-(void)function3;
@end
           

外置類目檔案:(Tool+ToolCategory.m)

@implementation Tool (ToolCategory)
-(void)function3{
    NSLog(@"我是function3");
}
@end
           

進階知識:

我們知道類目裡面不可以添加新的執行個體變量,會報錯;如果我們往類目裡面添加一個新的屬性呢?我們會發現,系統是不會報錯的。那是不是可以添加屬性呢?但是,到我們在主函數裡面設定還有通路該屬性的時候,就會報錯。那怎麼解決呢?
其實就像我們開始學設定器和通路器一樣,重寫設定器和通路器,但這裡不是普通的重寫,這裡就要用到我們IOS的一套機制了,即運作時機制。
           

運作時機制

IOS運作時機制,簡單來說,蘋果為開發者提供的一套運作時動态建立類、方法、屬性、的API,它是一套純c語言的API。
           

首先我們先随便設定一個屬性:

@property (nonatomic,strong)NSString *property2;
           

之後我們在.m檔案的類目裡面重寫getter和setter方法:

設定器我們要用到 objc_setAssociatedObject(<#id object#>, <#const void *key#>, <#id value#>, <#objc_AssociationPolicy policy#>)方法

該方法要寫入的屬性對應如下:
     <#id object#>   :給哪個對象的屬性指派
     <#const void *key#> :屬性對應的key
     <#id value#> : 設定屬性值為value
     <#objc_AssociationPolicy policy#> : 使用的政策
           

通路器我們要用到objc_getAssociatedObject(<#id object#>, <#const void *key#>)方法。

該方法要寫入的屬性對應如下:
     <#id object#>   :給哪個對象的屬性指派
     <#const void *key#> :屬性對應的key
           
-(void)setProperty2:(NSString *)property2{
    //_property2=property2;
    objc_setAssociatedObject(self, @selector(property2), property2, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSString *)property2{
//    return _property2;
    return objc_getAssociatedObject(self, @selector(property2));
}
           

最後我們在主函數看看類目裡面的方法和屬性的效果實作了沒:

ViewControl.m檔案:

Tool *tool=[[Tool alloc]init];
    [tool function1];
    [tool setValue:@"Rick" forKey:@"_name"];
    [tool setValue:@"aaa" forKey:@"property2"];
    [tool function2];
    [tool function3];
           

延展

我們之前說過類目可以添加私有的方法,其實指的是匿名類目,也就是延展。

作用

延展的作用就是定義自己的私有方法
           

類目跟接口檔案很像,就是把繼承父類那一塊換成一對小括号,表明它是一個延展(匿名類目)

@interface MyClass ()
-(void)testExtension;
@end
           
OC學習日記012(二)類目、延展類目、延展

下面是例子:

#import "MyClass.h"
#import "Myclass_Extension.h"
#pragma mark ---------------------------------
@interface MyClass ()
-(void)testExtension;
@end
#pragma mark ---------------------------------
@implementation MyClass
-(void)test1{
    NSLog(@"test1");
}
-(void)test2{
    NSLog(@"test2");
    [self testExtension];
    [self testExtension2];
}
-(void)testExtension{
    NSLog(@"我是延展testExtension");
}
-(void)testExtension2{
    NSLog(@"我是延展testExtension2");
}
@end
           

外置延展檔案:(Myclass_Extension.h)

#import "MyClass.h"
@interface MyClass ()
-(void)testExtension2;
@end
           
OC學習日記012(二)類目、延展類目、延展