你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 協議和 NSProxy 實現多繼承

協議和 NSProxy 實現多繼承

編輯:IOS開發基礎

OC 中一個類只有一個父類, 這就是單一繼承, 但是我們可以用協議NSProxy 實現多繼承

先說協議, 協議我們用的最多的地方,就是代理,其實代理不叫代理,叫委托, 這裡就不多說了,相信大家都很熟了
那麼 protocol 這個東西,是可以遵守多個的,遵守了之後,實現 protocol 中的方法,就OK 了,就是這麼簡單,輕松, easy

比如我有兩個協議, 分別是 YFPerson,YFChild

#import @protocol YFPerson @required
@property (nonatomic,copy,readonly)NSString *name;
- (NSInteger) age;
- (void)eat;
- (void)sleep;
@optional
- (void)play;
- (void)setName:(NSString *)newName;
@end
#import @protocol YFChild @required
- (NSString *)nickname;
- (void)introduceMyselfWithName:(NSString *)name nickname:(NSString *)nickname age:(NSInteger)age;
@optional
- (void)study;
@end

那麼, 我在新創建的一個 YFStudent 類中, 只要遵守上面兩個協議, 實現協議裡的方法, 就可以在一個類中,實現多個協議中的方法了.

YFStudent.m

- (NSString *)nickname
{
    return @"龍兒";
}

- (NSInteger)age
{
    return 19;
}

- (void)sleep{
    NSLog(@"sleep");
}

- (void)eat{
    NSLog(@"eat");
}

- (void)introduceMyselfWithName:(NSString *)name nickname:(NSString *)nickname age:(NSInteger)age
{
    NSLog(@"我叫%@,小名%@,今天%@歲了", name,nickname,@(age));
}

這樣, 我在控制器的 viewDidLoad 方法中,創建 YFStudent 對象, 然後就可以調協議中的任何方法了

- (void)viewDidLoad {
    [super viewDidLoad];

    YFStudent *student = [[YFStudent alloc]init];
    student.name = @"小龍女";
    [student eat];
    [student sleep];
    [student introduceMyselfWithName:student.name nickname:student.nickname age:student.age];
}

運行後,正確輸出


運行結果
現在再說 NSProxy, 這才是真的代理,不信去翻詞典

這個類是和 NSObject 平起平坐的, 而且這個類沒有 init 方法,也就是說,它只可以開辟一塊內存空間,而不能初始化. 那麼,我怎麼樣這個類可以變成任意一個類呢?

主要有這樣幾步,

  • 我先設置一個類 YFProxy, 繼承自 NSProxy

  • 為 YFProxy 設置一個 NSObject 屬性

  • 自定義一個轉換方法,相當於給 NSObject 屬性賦值

  • 然後通過這個屬性獲得調用方法的方法簽名

  • 為調用設置目標

  • 調用

我一步步說一遍
1.為外界暴露一個變身方法:

#import @interface YFProxy : NSProxy

- (id)transformToObject:(NSObject *)object;

@end

2.設置一個 NSObject 屬性

#import "YFProxy.h"

@interface YFProxy ()

@property (nonatomic,strong)NSObject *object;

@end

3.實現變身方法

- (id)transformToObject:(NSObject *)object
{
    self.object = object;
    return self.object;
}

4.重寫- (NSMethodSignature *)methodSignatureForSelector:(SEL)see方法獲得方法簽名

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    NSMethodSignature *methodSignature;

    if (self.object) {
       methodSignature = [self.object methodSignatureForSelector:sel];

    }else{

       methodSignature = [super methodSignatureForSelector:sel];
    }
    return methodSignature;
}

5.重寫- (void)forwardInvocation:(NSInvocation *)invocation方法改變調用對象,也就是說,讓消息實際上發給真正的實現這個方法的類

- (void)forwardInvocation:(NSInvocation *)invocation
{
    if (self.object) {
        [invocation setTarget:self.object];

        [invocation invoke];
    }
}
准備就緒,現在要開始變身了

假設我現在有兩個類,

YFPerson

#import "YFPerson.h"

@interface YFPerson ()

@property (nonatomic,copy)NSString *name;

@end

@implementation YFPerson

- (void)eat
{
    NSLog(@"%@正在吃飯",self.name);
}

@end

YFStudent

#import "YFStudent.h"

@interface YFStudent ()

@property (nonatomic,copy)NSString *studentNum;

@end

@implementation YFStudent

- (void)study
{
    NSLog(@"哥正在學習");
}

@end

那麼我怎麼用 YFProxy"繼承"這連個類呢?

  • 先初始化兩個純潔的對象

    YFPerson *person = [[YFPerson alloc]init];
    YFStudent *student = [[YFStudent alloc]init];
  • 為 YFProxy 開辟一塊內存空間

      YFProxy *proxy = [YFProxy alloc];
  • 變身

      [proxy transformToObject:person];
  • 這樣就可以自由自在地調用 Person 類的方法了,person 類的方法甚至是真私有的,都可以調得到,雖然報警告了

    [proxy performSelector:@selector(setName:) withObject:@"小明"];

    [proxy performSelector:@selector(eat)];
  • 再變

       [proxy transformToObject:student];
  • 這樣又可以調 Student類的方法了

    [proxy performSelector:@selector(study)];

是不是很神奇,當然,這只是初步的探討,還有很多基於 OC 運行時的東西值得我們去挖掘

上面就是兩種實現 OC 多繼承的兩種方法, 特別是第二種,我可以將 NSProxy 變成任意類,實現任意類的方法,並可以使用其屬性.
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved