// '类和结构体' 是人们构建代码所使用的一种通用且灵活的构造体, 我们可以使用完全相同的语法规则来为 '类和结构体' 定义属性 (变量 和 常量) 和添加方法, 从而扩展 类和结构体 的功能

// 与其他编程语言不同的是, Swift 并不要求你为自定义 类和结构去创建独立的接口和实现文件. 你所要做的是在一个单一文件中定义一个 类或是结构体, 系统将会自动生成面向其他代码的外部接口

// 注意 : 通常一个类的实例被称为对象, 然而在 Swift 中, 类和结构体的关系要比在其他语言中要密切,

// 类和结构体 的对比

// Swift 中类和结构体有很多共同点, 共同出在于:

// 1 : 定义属性用于存储值

// 2 : 定义方法用于提供功能

// 3 : 定义下标操作使得可以通过下标语法来访问实例所包含的值

// 4 : 定义构造器用于生成初始化值

// 5 : 通过扩展以增加默认实现的功能

// 6 : 实现协议以提供某种标准功能

// 与结构体相比, 类还有如下的附加功能

// 1 : 继承:     允许一个类继承另一个类的特征

// 2 : 类型转换:  允许在运行时检查和解释一个类实例的类型

// 3 : 析构器:    允许一个类实例释放任何其所被被分配的资源

// 4 : 引用计数:  允许对一个类的多次引用

// 注意 : 结构体总是通过被复制的方式在代码中传递, 不使用引用计数

// 定义语法

// 类和结构体 有着类似的定义方式, 我们通过 class 和 struct 来分别表示 类和结构体, 并在一堆大括号中定义他们的具体内容

class SomeClass{

// 这里定义类

}

struct SomeStructure{

// 在这里定义结构体

}

// 注意: 在你每次定义一个新类或者是结构体的时候, 实际上你是定义了一个新的 Swift 类型, 因此请使用 (如 SomeClass 和 SomeStructure 等), 以便符合标准 Swift 的大写命名风格, 相反的 , 请使用 '驼峰命名法' 为属性和方法命名, 以便和类型名区分

struct Resolution{

var width = 0

var height = 0

}

class VideoMode{

var resolution = Resolution()

var interlaced = false

var frameRate = 0.0

var name: String?

}

// 在上面的实例中我们定义了一个名为 VideoMode 的类, 用来描述一个视频显示器的特定模式, 这个类包含了四个变量存储属性, 第一个是 '分辨率' , 它被初始化为一个新的 Resolution 结构体的实例, 属性类型被推断为 Resolution , 新的 VideoMode 实例同时还会初始化其它三个属性.

// 类和结构体 实例

// Resolution 结构体 和 VideoMode 类的定义仅描述了什么是 Resolution 和 VidoeMode, 它们并没有描述一个特定的 分辨率 或者 视频模式, 为了描述一个特定的分辨率或者视频模式, 我们需要生成一个它们的实例

// 生成结构体和类实例的语法非常类似

let someResolution = Resolution()

let someVideoMode = VideoMode()

// 结构体和类都使用构造器来生成新的实例, 构造器语法的最简单形式是在结构体或者是类的类型名称后面跟随一堆空括号 (). 通过这种方式所创建的类或者结构体实例, 其属性均会被初始化为默认值

// 属性访问

// 通过使用点语法, 你可以访问实例的属性, 其语法规则是, 实例后面紧跟属性名, 两者通过点号 (.)连接

print("The width of someResolution is \(someResolution.width)")

// 你也可以访问子属性

print("The width of someResolution is \(someVideoMode.resolution.width)")

// 你也可以使用点语法为变量属性赋值

someVideoMode.resolution.width = 1280

print("The width is someVideoMode is now \(someVideoMode.resolution.width)")

// 注意 : 与 Objective-C 语言不同的时, Swift 允许直接设置结构体的属性的子属性, 上面的例子, 就是直接设置了someVideoMode中resolution属性的width这个子属性,以上操作并不需要重新为整个resolution属性设置新值。

// 结构体类型的成员逐一构造器

// 所有结构体 都有一个自动生成的成员 逐一构造器 , 用于初始化新结构体实例中成员的变量 , 新实例中各个属性的初始值可以通过属性的名称传递到成员的逐一构造器中

let vga = Resolution(width:640,height:480)

// 与结构体不同, 类实例没有默认的成员 逐一构造器,

// 结构体和枚举是值类型

// 值类型 : 被赋予给一个变量,常量或者被传递给一个函数的时候, 其值会被拷贝

// 实际上, 在 Swift 中,所有的基本类型: 整数:(Integer =). 浮点数(floating-point), 布尔值 (Boolean), 字符串(String), 数组 (Array), 字典(Dictionary), 都是值类型, 并且在底层都是以结构体的形式所实现,

// 在 Swift 中, 所有的结构体和枚举类型都是值类型, 这意味着它们的实例, 以及实例中所包含的任何值类型属性, 在代码传递的过程中都会被复制

let hd = Resolution(width: 1920, height:1080)

var cinma = hd

// 在将 hd 赋予给 cinma 的时候,实际上是将 hd 中所存储的值进行拷贝, 然后将拷贝的数据存储到新的 cinma 实例中, 结果就是两个完全独立的实例碰巧包含有相同的数值, 由于两者相互独立, 因此将 cinma 的 width 修改为 2048 并不会影响 hd 中的 width 的值

// 枚举中也遵循相同的规则

// 类是引用类型

// 与值类型不同, 引用类型在赋予到一个变量. 常量 或者被传递到一个函数的时候, 其值不会拷贝, 因此, 引用的是已经存在的实例本身而不是其拷贝

// 请看下面的这个示例

let tenEighty = VideoMode()

tenEighty.resolution = hd

tenEighty.interlaced = true

tenEighty.name = "1080i"

tenEighty.frameRate = 25.0

// 以上示例中, 声明了一个名为 tenEighty 的常量, 其引用了一个 VideoMode 类的新实例,在之前的实例中, 这个视频模式 被 赋予 1920 * 1080 的一个拷贝 (即 hd 的实例), 同时设置为interlaced,命名为“1080i”。最后,其帧率是25.0帧每秒。

// 然后

let alsoTenEighty = tenEighty

alsoTenEighty.frameRate = 30.0

// 类是引用类型, 所以 tenEighty 和 alsoTenEighty 实际上引用的是相同的 VideoMode 实例, 换句话说, 他们是同一种实例的两种不同叫法

// 下面,通过查看tenEighty的frameRate属性,我们会发现它正确的显示了所引用的VideoMode实例的新帧率,其值为30.0:

print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")

// 打印 "The frameRate property of theEighty is now 30.0"

// 需要注意的是 tenEighty 和 alsoTenEighty 被声明为 常量而不是 变量, 然而你依然可以改变 他们的属性值, 因为这两个常量的值并未改变, 因为他们并不存储 这个 videoMode 的实例, 而仅仅是对 VideoMode 实例的引用, 所以, 改变的是被引用的 VideoMode 的 frameRate 属性, 而不是引用 VideoMode 的常量的值

// 恒等运算符

// 因为类是引用类型, 有可能有很多个常量和变量在幕后同时引用同一个类实例.  (对于结构体和枚举来说, 这并不成立, 因为他们作为值类型, 在被赋予到常量, 变量或者传递到函数时, 其值总会被拷贝)

// 如果能够判定两个常量或者变量是否引用同一个类实例将会很有帮助, 为了达到这个目的, Swift 内建了两个恒等运算符

// 1 : 等价于 (===)

// 2 : 不等价于 (!==)

// 运用这两个运算符检测两个常量或者变量是否引用同一个实例

if tenEighty === alsoTenEighty {

print("is same")

}

// 请注意 : '等价于'(用三个等号表示,===) 与 '等于' (两个等号表示, ==)的不同

// '等价于' 表示两个类类型的 (class type) 常量或者变量引用同一个类型.

// '等于' 表示两个实例的值 '相等' 或 '相同', 因此相对于 '相等来说' ,这是一种更加合适的叫法

// 指针

// C语言, C++, OC 这些语言使用指针来引用内存中的地址, 一个引用某个引用类型实例的 Swift 常量 或 变量, 与 C语言 的指针类似, 但是并不是直接指向某个内存地址, 也不要求你使用星号 (*) 来表明你在创建一个引用, Swift 中这些引用于其它的常量 或 变量 的定义方式相同

// 类的结构体的选择

// 在你的代码中, 你可以使用类和结构体来定义您的自定义数据类型

// 然而,结构体总是通过值传递, 类实例总是通过引用传递, 这意味着两者使用不同的任务, 当你在考虑一个工程项目的数据结构和功能的时候, 你需要决定每个数据结构是定义成类还是结构体

// 按照通用的准则, 当符合一条或多条一下条件是, 请考虑构建结构体

// 1 : 该数据结构的主要目的是用来封装少量相关简单数据值

// 2 : 有理由预计该数据结构的实例在赋值或传递是,封装的数据将会被拷贝而不是引用

// 3 : 该数据结构中存储的值类型属性, 也应该被拷贝, 而不是被引用

// 4 : 该数据结构不需要去继承另一个既有类型的属性或者行为

// 举例来说, 一下情景中适合使用结构体

// 1 : 几何形状的大小, 封装一个 width 属性和 height 属性, 两者均为 Double 类型

// 2 : 一定范围内的路径

// 3 : 三维坐标系内一点, 封装 x, y ,z 属性, 三者均为 Double 类型

// 实际中,大部分的自定义数据构造都应该是 类,而不会是 结构体

// 字符串,数组,和 字典类型的 赋值 与 复制 行为

// Swift 中. 许多基本的类型, 诸如 String ,Array,  dictionary 类型均已结构体的形式实现,意味着 被赋值给新的变量或常量,他们的值会被拷贝

// OC 中 NSString, NSArray, NSDictionary 均以类的形式实现, 而不是结构体, 他们爱被赋值或者被传入函数或方法时, 不会发生值拷贝, 而是传递现有的实例引用

// 注意 : 以上对字符串, 数组, 字典的 '拷贝' 行为的描述, 在你的代码中, 拷贝行为看起来似乎随时发生,  然而, Swift 在幕后只在绝对必要时才会执行实际的拷贝,  Swift 管理所有的值拷贝以确保性能最优化, 所以你没必要去回避赋值来保证性能的最优化

swift 学习- 10 -- 类和结构体的更多相关文章

  1. Swift 学习笔记 (类和结构体)

    类和结构体是一种多功能且灵活的构造体.通过使用与现存常量 变量 函数完全相同的语法来在类和结构体中定义属性和方法以添加功能. Swift中不需要你为自定义的类和结构体创建独立的结构和实现文件.在Swi ...

  2. Swift语法学习之 类和结构体

    类和结构体 本页包括内容: 类和结构体对照 结构体和枚举是值类型 类是引用类型 类和结构体的选择 集合(collection)类型的赋值与复制行为 与其他编程语言所不同的是,Swift 并不要求你为自 ...

  3. Swift面向对象基础(上)——Swift中的类和结构体(上)

    学习来自<极客学院> import Foundation //1.定义类和结构体 /* [修饰符]calss 类名{ 零到多个构造器 零到多个属性 零到多个方法 零到多个下标 } 修饰符可 ...

  4. Swift面向对象基础(上)——Swift中的类和结构体(下)

    学习来自<极客学院> import Foundation class User { var name:String var age:Int init(name:String,age:Int ...

  5. Swift中的类和结构体的相同点与不同点

     相同点: 1.都是有内部变量和函数 2.都可以有内部下标方式去取属性 3.都可以有初始化函数 4.都可以用协议   不同点: 1.类有继承 2.类可以多重引用 3.类有析构  

  6. 【Swift学习】Swift编程之旅---类和结构体(十三)

    与其他编程语言所不同的是,Swift 并不要求你为自定义类和结构去创建独立的接口和实现文件.你所要做的是在一个单一文件中定义一个类或者结构体,系统将会自动生成面向其它代码的外部接口. 注意:通常一个类 ...

  7. 《从零开始学Swift》学习笔记(Day 25)——类和结构体定义

    原创文章,欢迎转载.转载请注明:关东升的博客 Swift中的类和结构体定义的语法是非常相似的.类使用class关键词定义类,使用struct关键词定义结构体,它们的语法格式如下: class 类名 { ...

  8. Swift类和结构体定义-备

    Swift中的类和结构体定义的语法是非常相似的.类使用class关键词定义类,使用struct关键词定义结构体,它们的语法格式如下: class 类名 { 定义类的成员 } struct 结构体名 { ...

  9. 站在OC的基础上快速理解Swift的类与结构体

    阅读此文章前,您已经有一定的Object-C语法基础了!) 2014年,Apple推出了Swift,最近开始应用到实际的项目中. 首先我发现在编写Swift代码的时候,经常会遇到Xcode不能提示,卡 ...

随机推荐

  1. tensorflow faster rcnn 代码分析一 demo.py

    os.environ["CUDA_VISIBLE_DEVICES"]=2 # 设置使用的GPU tfconfig=tf.ConfigProto(allow_soft_placeme ...

  2. 关于jQuery——attr方法和prop方法获取input的checked属性操作

    经常使用jQuery插件的attr方法获取checked属性值,获取的值的大小为未定义,此时可以用prop方法获取其真实值,下面介绍这两种方法的区别: 1.通过prop方法获取checked属性,获取 ...

  3. pyqt5-顶层窗口特定操作-图标和标题和不透明度

    图标: setWindowIcon(QIcon("resource/header_icon.png"))     设置窗口图标 icon=QIcon(r'大象.png')      ...

  4. js去掉某一属性

    将某一属性赋值为空就行了. 例如: document.getElementById('second').style.color = '';

  5. antd card 组件实现鼠标移入移出效果

    鼠标移出: 鼠标移入: import React, { Component } from 'react' import { Card, Icon, Avatar } from 'antd'; cons ...

  6. luogu P4148 简单题

    传送门 这题真简单,直接把\(CDQ\)给ban掉了 其实数据范围比较小可以直接二维树状数组,我们看数据范围,发现点的个数比N还小,可以考虑用一些奇怪的数据结构 说的就是你,\(KD tree\) \ ...

  7. python之字典的增删改查

    Python字典是另一种可变容器模型,且可存储任意类型对象,如字符串.数字.元组等其他容器模型.字典都是无序的,但查询速度快. 字典是一个key/value的集合,key可以是任意可被哈希(内部key ...

  8. yum2

    首先yum源的主配置文件为/etc/yum.conf文件.这个文件一般不用动,而我们配置具体的各个yum源的配置文件在/etc/yum.repo.d目录下,所有以repo结尾的文件都是yum源配置文件 ...

  9. Android逆向基础----APK文件结构

    参考这个博客 http://www.cnblogs.com/wangtianxj/archive/2010/06/13/1757639.html http://blog.csdn.net/bupt07 ...

  10. [转] 隐马尔可夫(HMM)、前/后向算法、Viterbi算法 再次总结

    最近工作需要优化LSTM-CRF经典模型中的维特比解码部分,发现对维特比一直是个模糊概念,没有get到本质,搜了一圈,发现一篇好文,mark 博主不让转载,mark个地址吧: https://blog ...