1. 程式人生 > >[X-Code7新功能之一]OC的泛型支援

[X-Code7新功能之一]OC的泛型支援

剛剛升級後,發現輸入提示等有所變化,上網看下,oc開始支援泛型了,這個絕對是好事啊。

說明oc還沒有被淘汰,蘋果還在繼續完善,希望能越來越好吧(肯定能,不差錢兒麼~)

#import <UIKit/UIKit.h>

@interface MyBase : NSObject

-(NSString*)description;
@end

@interface MyChild : MyBase
-(NSString*)description;
@end


/*MyTemplate<ObjectType: NSNumber*>這樣寫好使,能定義類型範圍*/
@interface MyTemplate<__contravariant ObjectType> : NSObject
{
@private
    /*目前在類裡面只有nsarray,nsset,nsdictionary可以識別~*/
    NSMutableDictionary<ObjectType,NSString*>* _Dic;
}
-(ObjectType)GetFirstObj;
/*函式的宣告可以用模版型別,但實現就不能用了,只能用id替代~*/
-(void) setValue:(ObjectType)value forKey:(NSString *)key;
@end

@interface ViewController : UIViewController

@end
#import "ViewController.h"
#import <UIKit/UIKit.h>

@implementation MyTemplate

-(instancetype) init
{
    if (self = [super init]) {
        _Dic = [[NSMutableDictionary<ObjectType,NSString*> alloc] initWithCapacity:3];
    }
    return self;
}
-(void) setValue:(id)value forKey:(NSString *)key
{
    [_Dic setValue:value forKey:key];
}
-(id)GetFirstObj
{
    if (_Dic.count == 0) {
        return nil;
    }
    NSEnumerator* ValueEnumer = [_Dic objectEnumerator];
    return [ValueEnumer allObjects].firstObject;
}

@end

@implementation MyBase
-(NSString*)description
{
    return @"MyBase";
}
@end

@implementation MyChild

-(NSString*)description
{
    return [NSString stringWithFormat:@"MyChild,Super %@", [super description]];
}
@end

@interface ViewController ()

@end

@implementation ViewController
{
    NSMutableArray<NSString*>* _ArrGenericity;
    NSMutableArray<MyBase*>* _ArrBase;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    _ArrGenericity = [[NSMutableArray<NSString*> alloc] initWithCapacity:3];
    NSString* str = @"Hello";
    /*只能用nstring*型別的了,變數、常量都可以*/
    [_ArrGenericity insertObject:str atIndex:0];
    [_ArrGenericity insertObject:@"World" atIndex:1];
    [_ArrGenericity enumerateObjectsUsingBlock:
     ^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"%@",obj);
    }];
    
    /*這個地方有寫不妥,不是很嚴格,只要是NSArray都可以~*/
    if ([_ArrGenericity isKindOfClass:[NSMutableArray<NSDictionary*> class]]) {
        NSLog(@"Kind Class is %@",[NSMutableArray<NSString*> class]);
    }
    /*不管什麼型別都不好使,看來只能用isKindOfClass判斷了,再試驗自定義*/
    if ([_ArrGenericity isMemberOfClass:[NSArray<NSString*> class]]) {
        NSLog(@"Member Class is %@",[NSArray<NSString*>  class]);
    }
    
    _ArrBase = [[NSMutableArray<MyBase*> alloc] initWithCapacity:3];
    MyChild* C1 = [[MyChild alloc] init];
    [_ArrBase insertObject:C1 atIndex:0];
    [_ArrBase enumerateObjectsUsingBlock:
     ^(MyBase * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"%@",obj);
    }];
    
    /*通過型別的輸出和isKindOfClass可以看出,對型別的檢查沒有增加元素型別*/
    if ([_ArrBase isKindOfClass:[NSMutableArray<MyChild*> class]]) {
        NSLog(@"%@",[NSMutableArray<MyBase*> class]);
    }
    
    /*物件聲明後,裡面的成員方法的構造型別自動被替換,這點很爽~,但裡class依然沒有加入型別判斷*/
    MyTemplate<NSString*>* m = [[MyTemplate<NSString*> alloc] init];
    [m setValue:@"World"forKey:@"hello"];
    NSLog(@"Class is %@, first Value is %@",[m class],[m GetFirstObj]);
    
    /*加不加__covariant關鍵字都有協變效果*/
    MyTemplate<MyBase*>* m1 = [[MyTemplate<MyBase*> alloc] init];
    MyChild* C2 = [[MyChild alloc] init];
    [m1 setValue:C2 forKey:@"c2"];
    NSLog(@"Class is %@, first Value is %@",[m1 class],[m1 GetFirstObj]);
    
    /*加__contravariant也有警告,不清楚原因啊~*/
    MyTemplate<MyChild*>* m2 = [[MyTemplate<MyChild*> alloc] init];
    MyBase* C3 = [[MyBase alloc] init];
    [m2 setValue:C3 forKey:@"c2"];
    NSLog(@"Class is %@, first Value is %@",[m2 class],[m2 GetFirstObj]);
    
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

總結下吧:

       1,沒有像c++那樣,在類宣告的地方能定義個模版型別,然後整個類到處都能用,包括實現部分。也許很快能這樣了。

       2,檢查型別的時候也沒有帶出模版的具體類,不是很嚴格~

參考:http://blog.csdn.net/leikezhu1981/article/details/47418011