Swift 的日常开发以及面试中会经常碰到类与结构体,下面我们来了解一下。
Class Person {
var age:Int
var name:String
init(age:Int,name:String){
self.age = age
self.name = name
}
deinit{
}
}
Struct Person {
var age:Int
var name:String
init(age:Int,name:String){
self.age = age
self.name = name
}
deinit{
}
}
一、相同点:
- 定义存储值的属性
- 定义方法
- 定义下标以使用下标语法提供对其值的访问
- 定义初始化器
- 使用 extension 来拓展功能
- 遵循协议来提供某种功能
二、不同点:
- 类有继承的特性,而结构体没有
- 类型转换使我们能够在运行时检查和解释类实例的类型
- 类有析构函数用来释放其分配的资源
- 引用计数允许对一个类实例有多个引用
三、类的初始化器
类编译器默认不会自动提供成员初始化器,结构体编译器会提供默认的初始化方法(前提是我们自己没有指定初始化器)
Struct Person {
var age:Int
var name:String
}
Swift 中创建类和结构体的实例时必须为所有的存储属性设置一个合适的初始值。所以类 Person 必须要提供对应的指定初始化器,同时我们也可以为当前的类提供便捷初始化器(注意:便捷初始化器必须从相同的类里调用另一个初始化器。)
1.指定初始化器
Class Person {
var age:Int
var name:String
init(age:Int,name:String){
self.age = age
self.name = name
}
}
2.便捷初始化器
class Person{
var age: Int
var name: String
init(_ age: Int, _ name: String) {
self.age = age
self.name = name
}
convenience init() {
self.init(age: 18, name:"小明")
}
}
注意点:
a.指定初始化器必须保证在向上委托给父类初始化器之前,其所在类引入的所有属性 都要初始化完成。
b.指定初始化器必须先向上委托父类初始化器,然后才能为继承的属性设置新值。如 果不这样做,指定初始化器赋予的新值将被父类中的初始化器所覆盖
c.便捷初始化器必须先委托同类中的其它初始化器,然后再为任意属性赋新值(包括 同类里定义的属性)。如果没这么做,便捷构初始化器赋予的新值将被自己类中其 它指定初始化器所覆盖。
d.初始化器在第一阶段初始化完成之前,不能调用任何实例方法、不能读取任何实例 属性的值,也不能引用 self 作为值。
3.可失败初始化器
参数的不合法或者外部条件的不满足,初始化失败。写return nil表明可失败初始化器在何种情况下会触发初始化失败
class Person{
var age: Int
var name: String
init?(_ age: Int, _ name: String) {
if age < 18 { // 例如小于18就是未成年人
return nil
}
self.age = age
self.name = name
}
convenience init?() {
self.init(age: 18, name:"小明")
}
}
4.必要初始化器
class Person{
var age: Int
var name: String
required init(age: Int, name: String) {
self.age = age
self.name = name
}
convenience init() {
self.init(age: 18, name:"小明")
}
}
class Student:Person{
var subjectName = subjectName
init(subjectName: String) {
self.subjectName = subjectName
super.init(age: 12, name: "小学生")
}
}