Swift 笔记(2) - 类和结构体

结构和类

Swift 中的结构体和类都可以存放数据和方法。
那么结构体和类有什么区别呢?
通常来讲,结构体是存储那些可以被当做值的对象,只用来存放封装的数据就可以了。

区别

类是引用类型的,然而结构体值类型的。这就说明,当你把类传入参数或者放在=右边时,传的是类的引用。而结构体只是单纯地被拷贝。
当把它们定义为 var 类型的时候,都可以改变成员变量并且更改它们(指针)的指向。
当用 let 修饰的时候,类和结构体有一些区别:

  • 常量类可以修改成员变量,但是不可以修改它的指向。
  • 常量结构体成员和指向都不可被修改。

定义一个类或结构体

class LocationInfo {
let name: String
let latitude: Double
let longitude: Double
//初始化函数,类中的成员必须在初始化中被初始化,除非它是 Optional 的
init(name: String, latitude: Double, longitude: Double) {
self.name = name
self.latitude = latitude
self.longitude = longitude
}
}

latitudelongitude 是相关的一组变量,可以把他们放进结构体里面。

struct Location {
let latitude: Double
let longitude: Double
}

这样,我们的 LocationInfo 类就可以修改了。

class LocationInfo {
let name: String
let location: Location
init(name: String, location: Location) {
self.name = name
self.location = location
}
}

但如果在现在想要构造一个 LocationInfo 的类得先要定义一个 Location 的结构,有些麻烦。
可以为类添加一个更方便的构造方法。

convenience init(name: String, latitude: Double, longitude: Double) {
let location = Location(latitude: latitude, longitude: longitude)
self.init(name: name, location: location)
}

类的继承

class Location3D : LocationInfo {
let height: Double
init(name: String, height: Double, latitude: Double, longitude: Double) {
self.height = height
let location = Location(latitude: latitude, longitude: longitude)
super.init(name: name, location: location)
}
}

语法没什么的,当子类都只属于自己的成员时,初始化需要在自己的构造里面实现。
子类的构造里必须调用父类的 init (不可以是 convenience init),初始化父类里面的成员。

当一个类不想让他被继承的时候,可以用 final 关键字修饰

重载函数

当子类重载父类的函数时,前面需要加上 override 关键字。

类的扩展(Class Extension)

类的扩展就是为类添加额外的功能,在 Swift 中可以添加属性和函数。
定义一个类的扩展:

class MyClass {
let foo1 = 123
let foo2 = 22
}

extension MyClass {
var foo3: Int {
return self.foo1 + self.foo2
}
}

其实把这些东西放到主类中也可以,但是为了逻辑的分离和代码的可读性,有时会添加类的扩展。

权限控制(Access Control)

类中的成员变量和方法都可以设置权限。

  • public : 所有的东西都可以获取。(主要应用于单元测试, 因为是在不同的 target 里面)
  • internal : 同一个库和应用才有权限,这是默认的等级。(必须在同一个 target 里面, 最适合库来使用,可以隐藏不想暴露的代码)
  • private : 只有这个源代码文件可以获取