zoukankan      html  css  js  c++  java
  • Swift类和结构体

    在C++中,相信不会有太多人去详细考究结构体和类的区别,因为二者关系实在不大。但在Swift中,结构体和类的关系非常大,它们的组成部分都包括:初始化器、实例方法、实例属性、类型属性、类型方法等等;二者也自然有很多的不同点,最大的不同点要数「类是引用类型,结构体是值类型」。本文着重对比阐述类和结构体的本质区别和它们的使用。

    类和结构体对比

    在Swift中,类和结构体有很多的共同点,包括:

    • Define properties to store values.
    • Define methods to provide functionality.
    • Define subscripts to provide access to their values using subscript syntax.
    • Define initializers to set up their initial state.
    • Be extended to expend their functionality beyond a default implementation.
    • Conform to protocols to provide standard functionality of a certain kind.

    和结构体相比,类还具有一些结构体不具备的特性:

    • Inheritance enables one class to inherit the characteristics of another.(结构体是不允许继承或被继承的)
    • Type casting enables you to check and interpret the type of a class instance at runtime.(结构体不存在多态,自然不存在所谓的「类型转换」了)
    • Deinitializers enable an instance of a class to free up any resources it has assigned.
    • Reference counting allows more than one reference to a class instance.

    类和结构体的定义

    类和结构体有着类似的定义方式。我们通过关键字class和struct来分别表示类和结构体,并在一对大括号{}中定义它们的具体内容,如下定义了一个结构体类型Resolution(用来描述一个显示器的像素分辨率)和一个类类型VideoMode(用来描述一个视频显示器的特定模式):

    struct Resolution {
    var width = 0
    var height = 0
    }
    class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var frameRate = 0.0
    var name: String?
    }
    实例以及属性访问

    定义结构体和类实例语法几乎一样:

    let someResolution = Resolution()
    let someVideoMode = VideoMode()

    和其他大多数语言一样,访问实例的属性使用.操作符。但是与OC不同的是,Swift允许直接设置结构体属性的子属性(在OC中可不允许),如下:

    println("The width of someVideoMode is (someVideoMode.resolution.widt
    h)")
    // 输出 "The width of someVideoMode is 0"
    someVideo.resolution.width = 12880
    println("The width of someVideoMode is now (someVideoMode.resolution.
    width)")
    // 输出 "The width of someVideoMode is now 1280"

    结构体的逐一成员构造器

    Swift为类和结构体都提供了默认的初始化构造器,其中有一个为结构体特别提供的默认构造器叫「逐一成员构造器」(memberwise initializer)。简而言之,使用该构造器,在创建实例时可以通过属性的名称设置它们的属性值,如下:

    let vga = resolution(640, height:480)

    更多关于结构体的「逐一成员构造器」信息,参考这里

    值类型和引用类型

    类是引用类型

    众所周知,类类型是「引用类型」。换句话说,对类类型变量赋值(譬如函数/方法的参数传值、返回值、变量赋值等),实际上操作的只是对象指针的拷贝。

    结构体和枚举都是值类型

    与「引用类型」对应的是「值类型」。值类型被赋予给一个变量,常数或者本身被传递给一个函数的时候,实际上操作的是对其进行拷贝。

    在Swift中,所有的基本类型都是值类型。换句话说,整型、浮点型、布尔值、字符串、数组、set、字典都是值类型,更进一步说,它们都是「结构体」类型。

    恒等运算符

    考虑到类是引用类型,有可能有多个常量或变量在后台同时引用同一个实例(当然,这对属于值类型的结构体和枚举而言是不成立的)。所以在很多时候需要判断两个常量或者变量是否引用同一个类实例,Swift为我们提供了两个运算符===!==,它们被称为「恒等运算符」(Identity Operators)。关于它们的用法就不啰嗦了,一眼就能看出来。

    类和结构体的选择

    相对于其他语言譬如C++,Swift中赋予了结构体更强大的功能,它和类类型有非常多的相似之处,都可以用来自定义数据类型,那么该如何选用呢?

    结构体实例总是通过「值传递」,类实例总是通过「引用传递」。这意味着二者适用于不同的任
    务。按照通用的准则,当符合一条或多条以下条件时,请考虑构建结构体:

    • 结构体的主要目的是用来封装少量相关简单数据值;
    • 有理由预计一个结构体实例在赋值或传递时,封装的数据将会被拷贝而不是被引用;
    • 任何在结构体中储存的值类型属性,也将会被拷贝,而不是被引用;
    • 结构体不需要去继承另一个已存在类型的属性或者行为;

    P.S:个人觉得,有了一定的使用经历之后,这个问题便不再是问题了,可能会变成一种下意识。

    集合类型的赋值和拷贝行为

    姑且也把String认为是集合类型吧!

    在OC中,NSString、NSArray、NSSet、NSDictionary以及相关类型都是类类型,因此,在传递过程中,它们的传递方式默认情况都是引用传递(对于属性,如果指定copy修饰词则有所不同,相对而言,比较复杂)。

    但是在Swift中,正如前文所述,String、Array、Set、Dictionary的本质都是「结构体」。无论在什么场合,它们的传递方式都是值传递。官方文档是这么描述的:

    Swift’s String, Array, and Dictionary types are implemented as structures. This means that strings, arrays, and dictionaries are copied when they are assigned to a new constant or variable, or when they are passed to a function or method.

    P.S:在第一个版本的《The Swift Programming Language》中有不同的描述,大概的意思是:

    Swift中数组(Array)和字典(Dictionary)类型均以结构体的形式实现。然而当数组被赋予一个常量或变量,或被传递给一个函数或方法时,数组(以及字典)的拷贝行为和其它结构体有些许不同。在Swift的后台中,只有确有必要,实际(actual)拷贝才会被执行。Swift管理所有的值拷贝以确保性能最优化的性能,所以你也没有必要去避免赋值以保证最优性能。

    P.P.S:上述这段话摘自《The Swift Programming Language》第一个版本中译版。可以看出,相对于第一个版本,当下Swift(1.2版本)做了一些修改,简化了设计理念,理解上也更容易一些。

  • 相关阅读:
    Objective-C NSString基本使用 类方法 self关键字
    Objective-C 封装 继承 多态
    Objective-C 类和对象
    Objective-C 第一个小程序
    python基础--函数作用域
    python基础--函数1
    python基础--文件操作
    python基础--集合
    python基础--字典
    python基础--列表,元组
  • 原文地址:https://www.cnblogs.com/FightingLuoYin/p/4608150.html
Copyright © 2011-2022 走看看