构造过程
类和结构体的存储属性必须在实例创建时,设定合适的初始值,可以提供默认值,也可以在构造器中提供初始值
1.构造参数
如果构造器的参数使用了外部参数名,必须使用,也可以用 _ 代替,不适用外部参数名
struct Celsius {
var temperatureInCelsius:Double //这里也可以提供初始值,也可以不提供,因为下面的构造器中在实力创建时会提供初始值
init(oneTemperature one :Double){
temperatureInCelsius = one + 10
}
init (twoTemperature two :Double){
temperatureInCelsius = two - 10
}
}
let oneCelsius = Celsius(oneTemperature: 0)
let twoCelsius = Celsius(twoTemperature: 20)
print("oneCelsius is :\(oneCelsius.temperatureInCelsius),towCelsius is \(twoCelsius.temperatureInCelsius)") //oneCelsius is :10.0,towCelsius is 10.0
class Question {
var text:String
var response:String?
let id :String
init(text:String){
self.text = text
id = text + "001" //构造过程中对常量的改变
}
func ask(){
print(self.text)
}
}
var question = Question(text: "Can i ask a question")
question.ask() //Can i ask a question
print(question.response) //nil,因为是可选的,如果不提供默认值,会自动的赋值为nil
print(question.id) // Can i ask a question001
2.默认构造器
类和结构体如果都没用提供构造器,则类默认的提供一个init(){}构造器,结构体提供一个逐一成员构造器
3.值类型的构造器代理
struct Point {
var x :Double = 0.0 ,y:Double = 0.0
}
struct Size {
var width :Double = 0.0 ,height:Double = 0.0
}
struct Rect {
var point = Point()
var size = Size()
init(){}
init(origin:Point,size:Size){
self.point = origin
self.size = size
}
init(center:Point,size:Size){
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
//self.point = center 在这里还没有调用指定构造器,不能直接赋值
//self.point 出现 error: use of 'self' in delegating initializer before self.init is called
//指向了init(origin:size:)构造器
self.init(origin:Point(x: originX, y: originY),size: size)
//self.point = center 在这里就不会发生错误
}
}
4.类的继承和构造过程
指定构造器:跟简单的构造器一样 init(parameters){} 总是向上代理
便利构造器:convince init(parameters){} 总是横向代理
二个阶段
(1)实例没有创建成功,内存还没有初始化完,会沿着构造器链往上执行,直到所有的属性给初始化完毕,实例创建成功,内存初始化完
(2)向下执行额外的属性赋值等操作
三条原则
(1)指定构造器必须继承父类的指定构造器
(2)便利构造器必须调用同一类的其他构造器
(3)便利构造器必须最终导致一个指定构造器被调用
四个检查
(1)指定构造必须先将引入的属性给初始化完毕才能将构造任务向上代理给父类的指定构造器
(2)指定构造器必须先向上代理给父类的指定构造器之后才能修改继承过来的属性
(3)便利构造器必须先横向代理给同一类中得指定构造器,才能任意的给属性赋值
(4)在第一阶段完成之前,不能调用任何实例方法,不能读取任何实例的属性,也不能引用self作为实例
5.可失败构造器
struct Animal {
let species :String
init?(species:String){
if species.isEmpty{return nil}
self.species = species
}
}
class Product {
let name:String!
init?(name:String){
//if name.isEmpty{return nil} 所有的存储属性必须在return之前
self.name = name
if name.isEmpty{return nil}
}
}
class CarItem: Product {
var quantity:Int!
var price:Int={
return 10
}() //可以通过闭包给属性赋值,但是在闭包最后必须加()代表立即执行
init?(name: String,quantity:Int) {
//if quantity < 1 {return nil} 所有的存储属性必须在return之前
self.quantity = quantity
//if quantity < 1 {return nil} super.init must be called before returning nil
super.init(name: name)
}
}