Objective-C的泛型
WWDC2015的明星是Swift。在Swift语言到2.0以后会被开源,这其中包括了protocol扩展和一个新的错误处理API。 苹果的小baby已经长成,并且意料之中的获得了开发者的关注。但是在iOS开发中Object-C并不会很快的推出历史舞台。 并且在WWDC2015中介绍了ObjC的一个很好地特性。我们下面就来谈一谈ObjC的这个新特性:泛型。
我们先看一看下面的代码:
let name: String
let surname: String
var friends: [Person]?
init(name: String, surname: String) {
self.name = name
self.surname = surname
}
}
非常简单。这里定义了一个名为Person
的类。虽然更应该被定义为一个struct,但是为了和ObjC做对比就先定义为类了。 这个类里面定义了一个属性friends
,一个Person对象组成的数组。Swift的数组是泛型的,可以包括Swift里面有的所有类型。 现在,假设我们有一个Person的对象,我们需要他的第一个朋友的名字。
编译器知道person.friends
是一个optional的包含Person
对象的数组。所以firstFriendName
是一个可空的字符串
很好,那么在ObjC里是怎么样的呢?
@property(nonatomic, copy, nonnull) NSString *name;
@property(nonatomic, copy, nonnull) NSString *surname;
@property(nonatomic, strong, nullable) NSArray *friends;
@end
在我们继续之前,我们先来聊一下nonnull和nullable这两个修饰符。这些叫做可空声明,是在Xcode6.3中引入的。 __nullable
可以有nil
或者NULL
值,而__nonnull
不可以。如果你不遵守这些规则,那么是编译不过的。
现在,我们可以回到泛型。我们无法在friends
数组中定义元素类型。参考Swift的例子,假设我们有类Person
的对象, 而且我们需要第一个朋友的名字。由于没有泛型,我们首先需要取到朋友数组的第一个元素。
由于Objective-C里没有泛型,person.friends.fristObject
只能定义为id
类型的,而不是Person
。 id
是一个可以指向任意类型的对象的指针,也就是id
指针指向的对象可以是任意类型的。 我们完全不能明确的知道person.friends.firstObject
是一个Person
对象。我们只能假设person.friends.firstObject
是一个Person
对象, 但是可以是NSString
类型的对象。
NSString *fristFriendWrongTypeVariable = person.friends.firstObject;
实用正确类型的对象是我们需要处理的。如果我们用了一个错误的类型,那么在运行时这个对象会接受到一个不支持的message, 这样就会报错了。要获取第一个朋友的名字,我们需要初始化另外的一个变量:
NSString *firstFriendName = firstFriend.name
这个例子非常简单,但是却明显的表明了ObjC需要额外多写一些代码,而且开发者,而不是编译器,需要负责类型的安全。
如果说ObjC急需什么Swift或者Java、C#早就已经有的特性的话,那么就一定是泛型了。幸好,Xcode7带来了一个轻量级的ObjC泛型。
@property(nonatomic, copy, nonnull) NSString *name;
@property(nonatomic, copy, nonnull) NSString *surname;
@property(nonatomic, strong, nullable) NSArray<Person *> *friends;
@end
现在我们可以定义集合里的元素类型了。
编译器知道firstFriendName
是NSString类型的。如果我们给一个变量赋值一个错误的类型的对象会发生什么呢?
我们会收到一个warning!
Swift会如何引入这个ObjC的Person
类呢
var surname: String
var friends: [Person]?
轻量的泛型不止适用于NSArray
。还适用于其他两个基础集合类-NSDictionary
和NSSet
。
另外,我们也可以在我们自定义的类型中使用这些轻量级的泛型:
- (void)doSomethingWithGeneric: (T)object;
@end
@implementation MyCustomClass
- (void)doSomethingWithGeneric:(id)object {
}
@end
[myCostomObject doSomethingWithGeneric:@"hello, world"];
如果我们使用错误的类型呢?
Xcode会给出一个警告。
但是有些东西需要注意:ObjC的自定义泛型类和泛型的集合在引入Swift之后行为并不一样。 NSArray
、NSSet
和NSDictionary
的类型在Swift中还是可用的。但是自定义的类的泛型参数在Swift中就不可用了。 所有的自定义类型又变回了AnyObject
。
Xcode7引入了轻量级泛型有什么好处呢?极大地减少了类型转换的代码。类型检测的责任从开发者转移到了编译器。 代码更加干净,类型更加安全。但是,这并不是全部。在Xcode7前,Swift调用ObjC的framework要非常小心。 每一个ObjC的集合元素都需要从AnyObject
类型做转换。引入了泛型之后就把ObjC和Swift的互操作的这个问题解决了。
from:https://netguru.co/blog/objective-c-generics
Objective-C的泛型的更多相关文章
- Automake
Automake是用来根据Makefile.am生成Makefile.in的工具 标准Makefile目标 'make all' Build programs, libraries, document ...
- iOS开发——新特性OC篇&Objective新特性
Objective新特性 Overview 自 WWDC 2015 推出和开源 Swift 2.0 后,大家对 Swift 的热情又一次高涨起来,在羡慕创业公司的朋友们大谈 Swift 新特性的同时, ...
- Objective C (iOS) for Qt C++ Developers(iOS开发,Qt开发人员需要了解什么?)
Qt/C++开发人员眼中的Obj-C 对于我们第一次自己定义iOS应用来说,对于来自Qt/C++开发人员来说,我不得不学习Objective-C相关语法与知识 为了让读者可以更easy理解这 ...
- 一起学 Java(三) 集合框架、数据结构、泛型
一.Java 集合框架 集合框架是一个用来代表和操纵集合的统一架构.所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.接口允许集合独立操纵其代表的细节.在面向对象的语言,接口通常形成一个 ...
- .NET面试题系列[8] - 泛型
“可变性是以一种类型安全的方式,将一个对象作为另一个对象来使用.“ - Jon Skeet .NET面试题系列目录 .NET面试题系列[1] - .NET框架基础知识(1) .NET面试题系列[2] ...
- C#4.0泛型的协变,逆变深入剖析
C#4.0中有一个新特性:协变与逆变.可能很多人在开发过程中不常用到,但是深入的了解他们,肯定是有好处的. 协变和逆变体现在泛型的接口和委托上面,也就是对泛型参数的声明,可以声明为协变,或者逆变.什么 ...
- 编写高质量代码:改善Java程序的151个建议(第7章:泛型和反射___建议106~109)
建议106:动态代理可以使代理模式更加灵活 Java的反射框架提供了动态代理(Dynamic Proxy)机制,允许在运行期对目标类生成代理,避免重复开发.我们知道一个静态代理是通过主题角色(Prox ...
- 6.在MVC中使用泛型仓储模式和依赖注入实现增删查改
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...
- C#泛型详解(转)
初步理解泛型: http://www.cnblogs.com/wilber2013/p/4291435.html 泛型中的类型约束和类型推断 http://www.cnblogs.com/wilber ...
- C# 泛型
C# 泛型 1.定义泛型类 在类定义中包含尖括号语法,即可创建泛型类: class MyGenericClass<T> { //Add code } 其中T可以遵循C#命名规则的任意字符. ...
随机推荐
- [Z]haproxy+keepalived高可用群集
http://blog.51cto.com/13555423/2067131 Haproxy是目前比较流行的一种集群调度工具Haproxy 与LVS.Nginx的比较LVS性能最好,但是搭建相对复杂N ...
- virtaulbox docker虚拟机使用主机代理shandowsocks
1.virtaulbox 配置NatNetwork File->Preference->network->add new nat network 2.virtaulbox 虚拟机配置 ...
- 839A Arya and Bran
A. Arya and Bran time limit per test 1 second memory limit per test 256 megabytes input standard inp ...
- iOS.BackgroundTask
Background Task 的运行时间在iOS 6及以前有大约10分钟左右,在iOS 7中有180秒. Reference: 1. Multitasking in iOS 7 http://www ...
- 将某视图View转换为UIImage
+ (UIImage *)getSharedScreenView{ UIWindow *screenWindow = [[UIApplication sharedApplication]keyWind ...
- Ubuntu安装R及R包
安装R $sudo apt-get update $sudo apt-get install r-base $sudo apt-get install r-base-dev 安装一些可能的依赖包 $s ...
- How to convert a PDF file to JPEGs using PHP
Hey, Today I would like to show you how we can convert PDF to JPEG using imagick extension. Imagick ...
- Use Laravel/homestead 环境维护基于 brophp 开发的老项目
1 前言 laravel/homestead 无疑是 laravel 项目开发的最佳环境. 如何使用这个环境维护基于 Brophp (或 Thinkphp) 开发的老项目呢? 以下是测试成功的步骤. ...
- MySQL 系列(一)安装
MySQL 系列(一)安装 以 Centos7 下安装 MySQL 5.6 为例. 一.环境准备 (1) 下载 下载地址: https://dev.mysql.com/get/Downloads/My ...
- Spring 常见注解
@Component:标准一个普通的spring Bean类. @Controller:标注一个控制器组件类. @Service:标注一个业务逻辑组件类. @Repository:标注一个DAO组件类 ...