购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

Tip 9

字面量转换

所谓字面量,就是指像特定的数字、字符串和布尔值这样,能够直截了当地指出自己的类型并为变量进行赋值的值。我们看下面的例子:

其中的3、Hello和true就称为字面量。

在Swift中,Array和Dictionary在使用简单的描述赋值的时候,使用的也是字面量,比如:

Swift为我们提供了一组非常有意思的接口,用来将字面量转换为特定的类型。对于那些实现了字面量转换接口的类型,在提供字面量赋值的时候,就可以简单地按照接口方法中定义的规则“无缝对应”地通过赋值的方式将值转换为对应类型。这些接口包括了各个原生的字面量,在实际开发中我们经常可能用到的有:

所有的字面量转换接口都定义了一个typealias和对应的init方法。拿BooleanLiteral-Convertible举个例子:

在这个接口中,BooleanLiteralType在Swift标准库中已经有定义了:

于是在我们需要自己实现一个字面量转换的时候,可以简单地只实现定义的init方法。举个不太有实际意义的例子,假如我们想实现一个自己的Bool类型,可以这么做:

这样我们就能很容易地直接使用Bool的true和false来对MyBool类型进行赋值了:

BooleanLiteralType大概是最简单的形式,如果我们深入一点,就会发现像StringLiter-alConvertible这样的接口要复杂一些。这个接口不仅类似于上面布尔值的情况,定义了StringLiteralType并接受其初始化方法,而且接口本身还需要实现下面两个接口:

这两个接口我们在日常项目中基本上不会使用,它们对应字符簇和字符 的字面量转换。虽然复杂一些,但是形式上还是一致的,只不过在实现StringLiteralConvertible时我们需要将这三个init方法都进行实现。

还是用例子来说明,比如我们有个Person类,里面有这个人的名字:

如果要通过String赋值来生成Person对象,可以这样改写这个类:

在所有接口定义的init前面我们都加上了required关键字,这是由初始化方法的完备性需求(见第39页)所决定的,这个类的子类都需要保证能够做类似的字面量转换,以确保类型安全。

在上面的例子里有很多重复的对self.name赋值的代码,这不是我们乐于见到的。一个改善的方式是在这些初始化方法中调用原来的init(name value:String),在这种情况下,我们需要在这些初始化方法前加上convenience(见第39页):

在上面Person的例子中,我们没有像在MyBool中做的那样,使用extension的方式来扩展类,使其可以用字面量赋值,这是因为在extension中,我们是不能定义required的初始化方法的。也就是说,我们无法为现有的非final(见第76页)的class添加字面量转换(不过也许在以后的Swift版本中能有所改善)。

总结一下,字面量转换是一个很强大的特性,使用得当的话对缩短代码和清晰表意都很有帮助。但这同时又是一个比较隐蔽的特性,因为你的代码并没有显式赋值或者初始化,所以可能会给人造成迷惑,比如上面例子中为什么一个字符串能被赋值为Person。你的同事在阅读代码的时候可能不得不去寻找这些负责字面量转换的代码进行查看(如果代码库很大,这不是一件容易的事情,因为你没有办法对字面量赋值用“Cmd+单击”进行跳转)。和其他的Swift的新鲜特性一样,我们究竟该如何使用字面量转换,它的最佳实践到底是什么,都还在研究及讨论中。因此在使用这样的新特性时,必须力求表意清晰、没有误解,这样代码才能经受得住考验。 AVER3AD7vfLKFV/lAa27f1Vj33dFp77WeEpj1SxUmhcOpf1CQn9L+jO80CCdVJJJ

点击中间区域
呼出菜单
上一章
目录
下一章
×