类的最基本特性就是封装, Swift 的类可以想见就是把 let 的常量, var 的变量, func 的方法写在 class 定义里。在此之上就涉及变、常量的初始,实例的初始化。Swift 的类定义与 Java 相比还是有些特别的地方,如属性不存在默认值,必须在构造函数中初始化; 构造函数还是沿用了 Objective-C 的方式,名称都是 init; 实例化时不需要 new 等等。
Swift 的类终于不用像 Objective-C 那样接口定义和实现分开来写了。
下面尽量用一个类声明来说明 Swift 类和对象更多的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
public class Vehicle { public static let CATEGORIES = "Suv" let vendor = "Honda" public let type: String final var year: Int var owner: String? private var color: String convenience init() { self.init("XR-V", year: 2014) self.color = "Red" } convenience init(_ type: String, year: Int) { self.init(type: type, year: year, color: "White") } init(type: String, year: Int, color: String) { self.type = type self.year = year self.color = color } deinit { print("I'm done") } func run() { print(self.owner) } } print(Vehicle.CATEGORIES) let car1 = Vehicle("Civic", year: 2015) print(car1.type) print(car1.owner) let car2 = Vehicle(type: "CR-V", year: 2013, color: "Blue") print(car2.color) |
说明:
- 类和属性,或方法都可以用 public/private 修饰
- 属性或函数可以是 static,同样表示是否是类的方法,只能通过类名来调用
- 属性和函数还可以用 final, final 只是说明属性和函数不可被子类重写,它并非 Java 的 final
- Swift 中类的属性必须初始化,在声明时或在构造函数中初始,不存在默认值,除非声明的是 Optional 属性,可默认为 nil
- 默认构造函数也是无参数的,构造函数是无返回类型的
- 构造函数之间可以互相调用,但发起调用的构造函数必须用 convenience 修饰
- 实例的初始化不需其他语言的 new 关键字,直接类名加括号来调用相应的构造函数,这像是调用 Scala object 的 apply() 方法
- 调用构造函数时,默认第一个参数的名称也不能省略,除非第一个参数声明为 init(_ type: String...) 的形式
- 属性或函数都是通过点
.
来引用,避开了那个不易书写的中括号[]
来发送消息的方式 - 析构器 deinit {},像 Java 的 finalize() 方法一样,只是它不能被称作一个函数
- 定义类时 class 和 struct 基本同意,可以试试把上面的 class 改成 struct,那么就必须把代码中的关键字 final 和 convenience 拿掉,并且不能有 deinit {}
结构和枚举是值类型,所以将一个结构或枚举赋值给另一个变量是产生一个拷贝
1 2 3 4 5 6 7 8 9 10 |
struct Shape { var name = "Circle" } var circle = Shape() var oval = circle oval.name = "Oval" print(oval.name) //输出 Oval print(circle.name) //输出 Circle |
而类是引用类型,把实例赋值给另一变量,它们将指向同一个对象
1 2 3 4 5 6 7 8 9 10 |
class Shape { var name = "Circle" } var circle = Shape() var oval = circle oval.name = "Oval" print(oval.name) //输出 Oval print(circle.name) //输出 Oval |
Swift 中比较两个变量是否指向同一个对象用 ===
对象,不是同一个对象的话用 !==
比较,有点像 Javascript 的做法
前面已了解了结构与类的最主要的一个区别,即结构是值类型,类是引用类型。同 C/C++, Objective-C 差不多的理由,我们既可用 struct 也能用 class 进行封装,何时用 struct 呢, 请参考如下:
- 结构主要是用于把相关联的数值组织在一块
- 在被赋值或作为参数传递时,是否需要产生一个拷贝; 结构的内部状态也是值类型
- 不需要继承行为时
一些结构的参考例子:Size(width, height), Coordinate(x, y). 及 String, Array, Dictionary 也是结构,所以它们赋值或传递时会产生拷贝,而 Objective-C 的 NSString, NSArray 和 NSDictionary 是类。
说到类怎能没有继承呢,继承一般反而简单些,Swift 用 class Car: Vehicle
格式来继承,势必涉及到方法的重载,子类中如何调用父类的构造函数,属性或方法的可见性,用时再细究。
参考:1. Classes and Structures
本文链接 https://yanbin.blog/swift-learning-class-object/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。