由苹果公司在2014年创建的Swift是一种流行的开源语言,用于构建iOS应用程序,已经获得了一个强大的开发者社区和丰富的第三方内容。
像其他几乎所有的编程语言一样,Swift有自己的规则和语法。在本指南中,我们将看看Swift中的类型转换,这是现代面向对象编程语言中的一个流行概念。
什么是Swift中的类型?
从本质上讲,类型是类的原始等价物,用于表示存储在变量中的数据种类。由于每个类都与其他类不同,所以数据类型也不同,允许开发人员根据它们持有的数据类型来区分变量。对数据类型进行分类可以防止类型不匹配,这是编译时的一个常见错误。
对于编译器来说,类型是不相关的。如果存储在一个变量中的数据符合在流程中稍后进行的操作,进程将相应地运行。
然而,如果类型不匹配导致流程中断,你会看到一个编译错误。即使类型不匹配没有明确地破坏流程,它也可能在编译过程中没有被注意到,导致程序运行时出现意想不到的结果。
Swift是一种强类型的编程语言。Swift中的每个变量都有一个与之相关的类型,一旦一个类型被分配给一个变量,它就不能存储任何其他类型的数据。
弱类型语言在这方面没有那么严格。例如,在PHP和C等语言中,你可以在一定程度上改变数据类型,以获得代码的更大灵活性。
什么是类型转换?
使用类型的限制迫使一种语言失去了很大一部分的灵活性。类型转换提供了一种方法来获得一些灵活性。
并非所有的类变量都持有像整数和字符串这样的原始数据。现代应用程序的大部分逻辑都依赖于自定义对象,而这些对象是通过类实现的。从现在开始,我们将用类型来指代原始数据类型和类。
类型转换是大多数面向对象语言中使用的一种编程范式,它允许开发者把一种类型的对象当作另一种类型的对象。虽然类型转换一开始可能没有什么意义,但它有助于简化现代应用程序中的许多程序。
类型转换并不改变相关的对象。相反,它改变了用于描述该对象的类型。例如,你显然不能把一个持有字符串的对象的类型从string
改为integer
,因为在现实生活中,把一个句子当作一个数字是没有意义的。
为了使类型转换发生,相关对象的原始类型和新类型必须是彼此的子类或超类。假设一个叫做Vehicle
的类有两个子类,Car
和Truck
。你可以把一个类型为Car
的对象投给Vehicle
,反之亦然;或者把Truck
投给Vehicle
,反之亦然。
现在,我们假设有另一个叫做Ship
的类,它与Truck
、Car
或Vehicle
没有关系。你将不能把它的对象投到上面给出的任何类型中。
上投
上投是用来通过使用一个类本身的变量来概括该类的一系列子类的。让我们考虑一下使用Car
,Truck
, 和Vehicle
的例子。
我们在前面提到,Car
或Truck
可以被类型转换为Vehicle
。一个子类的对象被类型转换为其超类的对象。可以把它看作是在类的层次结构中向上移动。
上投允许你将任何类型的Vehicle
存储在一个类型为Vehicle
的引用中:Car
,Truck
, 等等。我们已经知道,这些都是同一个类的后代,Vehicle
,而且它们必然有一些相似之处。将它们的对象上传到Vehicle
类中,使用了这种泛化,让我们使用循环和其他常规范式运行操作。
下面是一个上传法的例子。
let truck:Truck = Vehicle(wheels:8)
复制代码
在上面的代码块中,你声明了一个名为truck
的引用,它的类型是Truck
。接下来,你用一个Vehicle
的实例来初始化它,它有八个轮子。你可以看到引用变量的类型注释和分配给它的对象是完全不同的。
如前所述,我们可以执行这个操作,因为Truck
和Vehicle
属于同一个类的层次结构。这完全就像说卡车是车辆一样,在逻辑上是正确的。
在上面的例子中,上播是隐含的。然而,你可以通过运行下面的代码使其可见。
let truck:Truck = Vehicle(wheels:8) as Truck
复制代码
稍后,我们将更详细地介绍隐式上播。
下传
下投是与上投相反的,它指的是将一个父类类型的对象投给其子类的对象。下投是用来重新转换先前被上投的子类对象,以实现泛化。
比方说,你拥有两辆汽车和三辆卡车。如果你把它们存储在一个共享数组中,类型推理将决定数组的类型为Vehicle
,这是两个类型的共同父类。
如果你试图从数组中获取一个项目,你会得到一个类型为Vehicle
的对象。要把它变回原来的类型,你需要把它下移到一个Truck
或Vehicle
。
必须了解的是,列表中的车辆并非都是汽车,这可能会在某些情况下导致下转换的失败。为了解决这个问题,我们将使用两种类型的下划线操作符,我们将在后面介绍。
水平类型转换
请注意,Car
和Truck
有一个共同的超类,但是,你不能把一个类型为Car
的对象投到Truck
,反之亦然。它们既不是彼此的子类也不是彼此的超类。因此,水平铸造是无效的,如果你试图将一个Car
铸造到一个Truck
,你会得到一个错误。
Swift中的类型转换操作
为了执行上述操作,你将使用以下运算符。
as
as
运算符被用来上投对象。然而,在大多数情况下,上投是以隐式方式进行的,所以你不会经常使用as
。
重申一下,这里有一个将Chair
上传到Furniture
的例子。
let furniture:Furniture = Chair(legs: 4) as Furniture
复制代码
as?
as?
操作符用于可选的下移,是Swift中可用的两个下移操作符之一。当你不确定一个对象是否能被成功下传时,请使用as?
。
如果你试图从一个不同的类层次结构中下移一个对象,你的程序在遇到错误时就会返回一个nil
值。为了验证下转换是否成功,你可以把一个简单的检查nil
。
你可以在我们的Vehicle
例子中使用as?
操作符。
let truckObject = vehiclesArray[0] as? Truck
复制代码
你指示控件访问数组中的第一个对象,将其下传到一个Truck
,并将结果存储在truckObject
变量中。
如果下移成功,你会在truckObject
中找到一个Truck
实例。如果失败,truckObject
将指向nil
。然后你可以通过运行来检查nil
。
if truckObject != nil {
print("The reference points to some value!")
} else {
print("The reference points to nil, and so the downcast was unsuccessful")
}
复制代码
as!
as!
操作符用于强制下转换,它只在类型转换操作可能时返回一个对象。如果你试图从不同的类层次结构中下移一个对象,你的程序将遇到一个致命的错误。
下面是你如何使用as!
操作符与我们的Vehicle
例子。
let carObject = vehiclesArray[1] as! Car
复制代码
上面这行代码是指示控件从数组中访问第二个对象,将其下移到一个Truck
,并将结果存储在truckObject
变量中。如果下转换失败,程序就会崩溃。
考虑到以上几点,只有当你确定你要下传的对象属于类的层次结构时,你才应该使用as!
操作符,并且操作会成功完成。
你也可以在以下情况下使用as!
操作符:如果类型不匹配,代码的流程需要中断,这表明在中间计算中可能会有意外的结果。
is
is
操作符用于检查一个实例的类型。使用is
操作符进行类型检查的结果是Bool
,它表示类型是否匹配,如下面的代码块所示。
let car: Car = Car(wheels: 4)
if car is Car {
print("It is a Car.")
} else if car is Truck {
print("It is a Truck.")
}
复制代码
输出结果是。
It is a Car.
复制代码
你也可以使用is
操作符来检查任何隐含的上播。让我们考虑一个例子。
let car: Car = Vehicle(wheels: 4)
print(car is Car)
print(car is Truck)
print(car is Vehicle)
复制代码
上面的代码的输出是:。
true
false
true
复制代码
输出结果表明,汽车引用的类型是Car
,隐式上播的类型是Vehicle
。由于水平投射是不可能的,Car
不可能属于Truck
。
自己尝试一下
在这篇文章中,你了解了Swift中的类型和类型投射,并涵盖了用于类型投射对象的各种操作符。
类型转换是一个概念,它使面向对象的编程非常强大和灵活。由于能够通过上投和下投在类的层次结构中上下移动,你可以根据需要利用泛化。
保留所有信息的关键是要不断练习。我希望你喜欢这篇文章。编码愉快
The postType casting in Swift appeared first onLogRocket Blog.