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#命名规则的任意字符. ...
随机推荐
- python time 和 datetime 模块
时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量.我们运行“type(time.time())”,返回的是float类型. 格式化的时间字 ...
- c#多线程下的进程同步SignalAndWait 使用简单说明
解释:向一个 WaitHandle 发出信号并等待另一个进入信号. 总体概述: .NET Framework中提供一些类用于手动进行线程间的访问同步.这些类主要分为3大类别(但正如下文中会看到的这些类 ...
- android使用Pull解析来自服务器的xml文件时出现错误以及解决方案
直接上代码,代码中有详细注释: 1 public class CheckUpdateManager { 2 private static final String TAG = "CheckU ...
- Maven 系列 一 :Maven 快速入门及简单使用
开发环境 MyEclipse 2014 JDK 1.8 Maven 3.2.1 1.什么是Maven? Maven是一个项目管理工具,主要用于项目构建,依赖管理,项目信息管理. 2.下载及安装 下载最 ...
- (O)JS:执行环境、变量对象、活动对象和作用域链(原创)
var a=1; function b(x){ var c=2; console.log(x); } b(3); ·执行环境(execution context),也称为环境.执行上下文.上下文环境. ...
- MySQL5.7的安装(CentOS 7 & Ubuntu 16.04)
CentOS 通过 yum 安装MySQL5.7 Yum Repository 下载地址:https://dev.mysql.com/downloads/repo/yum/ 选择相应的版本进行下载:R ...
- Serial-mcu
任务: PC按下1键, mcu连续发送a, 当PC按下2键, 终止发送 查询: #include <reg52.h> #define uint unsigned int #define u ...
- PHP 过滤特殊符号
function strFilter($str){ $str = str_replace('`', '', $str); $str = str_replace('·', '', $str); $str ...
- ios微信打开网页键盘弹起后页面上滑,导致弹框里的按钮响应区域错位
input失去焦点,页面被顶起没有还原,所以就有以下的方法来处理 $("input").blur(function(){ setTimeout(() => { co ...
- Vue单页面应用
单页面应用指一个系统只加载一次资源,然后下面的操作交互.数据交互是通过router.ajax来进 行,页面并没有刷新:<1>在vue搭建的环境里面怎么有没有公用的css和js? ...