Swift的类型推断会不会造成类型不确定的困扰?

Swift的类型推断会不会造成类型不确定的困扰?

标签(空格分隔): Swift 强类型 类型推断

前言

相信看过《The Swift Programming Language》的人对这门语言会有初步的印象:强类型。此外一个经常提到的特点就是类型推断。
强类型的意思就是一个变量或者常量要有确定的类型。类型推断的意思是编译器可以根据赋值的情况(可能还有其他线索)推断出变量或者常量的类型,表面上和某些弱类型语言的写法类似:

// 变量intValue没有显式声明一个特定的类型,编译器会根据其赋值语句推断出它的类型为Int
var intValue=10;

我们知道,如果是js这样写没有问题,语法就允许。换做ActionScript(AS3),这样写编译不会报错,但是会给出警告,提示你intValue没有指定类型。那么,Swift中这样写会怎么样呢?答案是可以编译,而且没有警告。在《The Swift Programming Language》中存在大量这样的写法,给人的感觉是在提倡这样写。那么号称强类型的语言怎么这点上和js如此类似呢?这种不确定的类型,会不会给团队协作造成困扰?调用他人的程序,如果对方这样声明属性还能不能获得属性的类型了?本文就要说明这个问题。

猜测

最近在看斯坦福大学的iOS开发视频,里面有一个细节:在类中定义了不是Optional的属性1,如果没有给出初始值,同时没有构造方法或者构造方法中也没有赋值初始化属性,是无法通过编译的,也就是说如果不是可以为nil的属性,必须要给出初始值。这点写过AS3程序的人会特别在意,因为AS3的基本类型都是有一个默认值的,所以即便没有给基本类型的属性赋值,也是允许的。这是两种语言对于属性初始值检查的差异。这个细节也说明既不声明类型也不给初始值,是无法通过初始化检查的。据此我猜测Swift编译器对类型的检查绝对要比AS3严格,前言中Swift的两个特点看似矛盾,其实是假象。

证实

为了验证猜测,在XCode中动手试试就好了。
我会在一个类A中通过类型推测的方式定义属性,在类之外对这个属性进行访问,观察能否得到具体的类型。

声明一个类:

public class ClassA
{
    var intValue=10;
    var doubleVlaue=10.0
    var strValue:String{
        get{
            return "\(intValue)"
        }
        set{
            intValue=0
        }
    }
}

ClassA具有两个存储属性和一个计算属性,两个存储属性都依赖类型推断声明。经过尝试,计算属性的类型不可省略,省略后无法通过编译。

在另外一个类中实例化ClassA,访问实例的属性:

let s:ClassA=ClassA();
@IBAction func accessTest(sender: UIButton) {
    s.intValue=1;
    s.doubleVlaue=23;
}

以上代码可以通过编译。以下的尝试不会通过编译:

s.intValue=0.1;
 s.doubleVlaue="dfdsf";

在编辑器中,鼠标经过类型“模糊”的属性时按下“option”键,鼠标指针变为问号,点击以下鼠标左键,弹出的提示信息中会明确显示属性的类型。上面不能编译通过的赋值语句都是类型不符合造成的。

以上得到的结论就是:通过类型推断获得的类型,并不是在声明范围内的权宜之计,而是持久的改变,就像你自己补全了声明一样。

Swift作为一门强类型语言,声明一个常量或者变量,类型是不可缺少的。类型推断只是一颗语法糖,让程序员偷懒,但不要真的以为这样声明的内容没有一个确定的类型。

  1. 不是Optional的属性,可以理解不可以为nil的属性。

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...