当前位置: 首页 > article >正文

09、Swift中的class

09、Swift中的class

  • 1、struct 和 class的差异
    • 1.1 引用类型必须明确指定init方法
    • 1.2 引用类型关注的是对象本身
    • 1.3 引用类型默认是可以修改的
  • 2、理解class类型的各种init方法
    • 2.1 默认init
      • 2.1.1 方式一
      • 2.1.2 方式二
    • 2.2 Convenience init
    • 2.3 Failable init
  • 3、继承
    • 3.1 init方法
      • 3.1.1 init的继承
      • 3.1.2 重载init方法
      • 3.1.2 init的初始化过程
    • 3.2 永远不要重定义继承而来的默认参数
    • 3.3、重写继承方法的替代方案
      • 3.3.1 重写替代方案一:Template method
      • 3.3.2 重写替代方案二:基于函数的Strategy模式
      • 3.3.3 重写替代方案三:基于class的strategy模式
  • 4、使用访问控制管理代码
  • 4.1 从module说起
    • 4.2 使用public定义开放且不需要修改的类和方法
    • 4.3 使用open定义开放且需要扩展的接口
    • 4.4 默认的internal
    • 4.5 使用fileprivate在单个文件内共享代码
    • 4.6 使用private定义在一个词法单位内使用的代码

1、struct 和 class的差异

作为Swift中的另外一种自定义类型,从语法上来说,class和struct有很多相似的地方,它们都可以用来自定义类型、都可以有properties,也都可以有methods。
作为Swift中的引用类型,class表达的是一个具有明确生命周期的对象,我们需要关注这类内容的“生死存亡”,而值类型,我们更多关注的,就真的只是它的值而已。

1.1 引用类型必须明确指定init方法

首先,Swift并不会为class自动生成默认的init方法。如果我们不定义它,Swift编译器会报错。

1.2 引用类型关注的是对象本身

其次,class和struct对“常量”的理解是不同的。我们分别定义一个PointRef和PointValue的常量:

let p1 = PointRef(x: 0, y: 0)
let p2 = PointValue(x: 0, y: 0)

同样是常量,当我们修改p2的属性时,编译器会报错:p2 is a let constant:

p2.x = 10 // Compile time error

但是,我们却可以修改p1:

p1.x = 10 // OK

这是因为,p2作为一个值类型,常量的意义当然是:“它的值不能被改变”。但是p1作为一个引用类型,常量的意义则变成了,它可以修改自身的属性,但不能再引用其他的PointRef对象。如果我们尝试让p1引用另外一个PointRef对象,就会发生下面的错误:

p1 = PointRef(x: 1, y: 1) // Compile time error

以上就是引用类型代表的“对象”和值类型代表的“值本身”在语义上的差别。而这种差别,还体现在了对它们各自进行赋值之后的表现上:

var p3 = p1
var p4 = p2

这之后,当我们使用===比较p1和p3的时候,得到的结果是true:

p1 === p3 // true

并且,当我们修改了p3之后,p1的值,会一并修改:

p3.x = 10
p1.x // 10

但是,当我们修改了一个值类型时,却并不会这样:

p4.x = 10
p2.x // 0

1.3 引用类型默认是可以修改的

由于引用类型关注的是其引用的对象,而不是对象的值。因此,它的方法默认是可以修改对象属性的。例如:

class PointRef {// ...func move(to: PointRef) {self.x = to.xself.y = to.y}
}

但是,对于值类型PointValue来说move必须用mutating来修饰:

struct PointValue {// ...mutating func move(to: PointValue) {self.x = to.xself.y = to.y}
}

所以,修改一个struct的本意,实际上是你需要一个全新的值。
最后,还有一点要说明的是,在PointValue里,我们可以直接给self赋值:

mutating func move(to: PointValue) {self = to
}

编译器知道对一个值类型赋值就是简单的内存拷贝,因此,他会自动用to的每一个属性设置self的对应属性。但是,对于一个引用类型来说,你却不能这样:

class PointRef {// ...func move(to: PointRef) {self = to // !! Compile time error !!}
}

在class的方法里,self自身是一个常量,我们不能直接让它引用其它的对象。

2、理解class类型的各种init方法

2.1 默认init

2.1.1 方式一

给每一个属性都添加默认值

class Point2D {var x: Double = 0var y: Double = 0
}调用
let origin = Point2D()

2.1.2 方式二

通常,我们还是至少会为class添加一个memberwise init方法。哪怕它就是一个逐个属性赋值的方法。

class Point2D {var x: Doublevar y: Doubleinit(x: Double = 0, y: Double = 0) {self.x = xself.y = y}
}
为了让一个对象可以默认构造,class必须提供一个不需要参数的init方法,并且,这个方法必须初始化class的每一个属性。在Swift里,这种真正初始化class属性的init方法,叫designated init,它们必须定义在class内部,而不能定义在extension里,否则会导致编译错误。另外,除了designated init方法之外,还有一类不真正初始化class属性的方法。

2.2 Convenience init

extension Point2D {convenience init(at:(Double,Double)) {self.init(x:at.0,y:at.1)}
}let point = Point2D(at: (2.0,2.0))
这时,我们就需要把作为参数的(2.0, 2.0)拆开成Point2D的每一个属性,然后调用designated init。对于完成这类任务的init方法,就叫做convenience init

可以看到,对于convenience init来说,它有两个要素:

  • 使用convienience关键字修饰;
  • 必须最终调用designated init完成对象的初始化;如果我们直接在convenience init中设置self.x或self.y,会导致编译错误;

2.3 Failable init

例如,我们希望用一个String tuple初始化Point2D:

let point44 = Point2D(at: ("4.0", "4.0"))

参考之前的convenience init,我们可以如法炮制一个:

class Point2D {// ...convenience init?(at: (String, String)) {guard let x = Double(at.0),let y 
http://www.lryc.cn/news/2420483.html

相关文章:

  • 淘宝宝贝详情页设计指南:从构思到实现,打造高转化率的页面
  • 详解箭头函数和普通函数的区别以及箭头函数的注意事项、不适用场景
  • PL/SQL 例外(异常) exception
  • windows下钩子的使用
  • 设计测试用例(蘑菇街web的登录页面)
  • Windows中DLL文件基本原理及修改方法
  • MySQL Cluster 集群部署
  • navicat for mysql cannot create file
  • Code Jam练习
  • 这几个免费资源网站太强了!老司机们都收藏了!
  • 影视后期制作的探索:C4D与MAYA的比较
  • 2024年五一数学建模竞赛C题思路解析+代码+论文
  • 2024年软件测试工具总结 —— 性能测试工具
  • 微信网站域名如何做防封和防屏蔽技术
  • VC 下Microsoft Speech SDK 5.1 开发小结
  • 戴尔不再提供电脑和手机互联功能:Mobile Connect应用将终止服务(学习资料)
  • Flex的item Editor,itemReder小结 ——(学习自FlexCookbox)
  • echarts 地图_博客 城市访问量统计并且通过Echarts+百度地图展示
  • 什么是代理服务器?如何在编程中使用它?
  • 免费收录网站搜索引擎登录口
  • Spring 基于.xml的bean配置
  • CCF 期刊、会议 推荐目录
  • 基于JAVA医院医护人员排班系统计算机毕业设计源码+系统+mysql数据库+lw文档+部署
  • 使用CSS3画出一个叮当猫(超级可爱!)
  • 程序员电影,荧屏里的程序员形象
  • 关于list_entry
  • 抖音短视频实操:抖音热门视频的分类特点,如何选择视频内容(上)
  • dlib人脸68个特征点检测 Win10_VS2019编译过程和实验结果
  • windows WinHttp
  • Java之SVN快速入门,服务器VisualSVN和客户端TortoiseSVN的使用,IDEA下的SVN的配置和使用,SVN的目录规范