美文网首页
类的构造和析构

类的构造和析构

作者: 架构师的一小步 | 来源:发表于2018-12-17 11:10 被阅读0次

默认构造函数

  • 当类的所有属性都预先设置了值,并且没有自己定义任何构造函数,swift会为我们默认创造一个构造函数
class TV{
var working=false
func open(){
 self.working=true
}
func close(){
self.working=false
}
}

let tv=TV()

自定义构造函数

  • 当没有构造函数时候,需要自己定义构造函数,关键点:需要把类的所有没有初始化的函数初始化好
  • 用法:class TV没有任何参数所以为(),用init关键字构建初始化函数,组合成init(){}
//用户初始化函数不需要传参的
class TV{
var working:Bool
func open(){
 self.working=true
}
func close(){
self.working=false
}
init(){
 working=false
}
}

let tv=TV()

//需要穿参数的
class TV{
var model:String
var working:Bool
func open(){
 self.working=true
}
func close(){
self.working=false
}
//这里设置参数,证明用户初始化函数,需要传递一个参数
init(model:String){
 working=false
//这里用self.model访问的属性model,是为了区别model,如果不加self访问的会是这个参数model,证明他们两个不是同一个值
self.model=model
}
}

let tv=TV(model:"一个新的开始")

继承和构造

  • 继承类没有实现自己的构造函数时候,会继承基类的所有构造函数
//父类
class TV{
 var model:String
init(model:String){
 self.model=model
}
init(){
 self.model="old-man"
}
}
let tv=TV(model:"old-man")

//子类
class GameTV:TV{
 func playGame() -> Void{
print("start play game...")
}
//如果想要自己的初始化值需要重载init函数,和之前重载方式一样用override关键字进行重载定义
override init(){
 super.init()
self.model="game-tv1"
}
}
  • 继承类如果实现或者重载了基类的任意一个构造函数,那么继承类就不会自动继承基类的其他构造函数了,调用其他构造函数会报错

继承类的构造函数

  • 如果继承类有一个参数没有默认值,调用基类的构造函数之前,要把继承类自己的参数先初始化后再调用基类的

  • 继承类的属性先于基类初始化
  • 继承类的属性必须在初始化之后,调用基类构造函数
//基类
class TV{
 var model:String

init(model:String){
  self.model=model
}
}

//报错写法
class GameTV:TV{
 var playingGame:Bool
init(){
// self.playingGame=false要放到super.init之前
 super.init(model:"lcd")
 self.playingGame=false
}
}

//
//正确写法
class GameTV:TV{
 var playingGame:Bool
init(){
 self.playingGame=false
 super.init(model:"lcd")
}
}

Tow phase

1.阶段1,初始化所有的属性
2.阶段2,初始化所有方法


Phase 1:

  • 自身Stored Property必须全部初始化
  • 调用基类的构造函数
  • 在调用基类构造函数之前,不能访问基类的Stord Property
  • 不能调用实例方法

Phase 2:

  • 所有的基类的构造函数均已调用,所有Stored Property均有初始值
  • 对构造函数而言,已经是一个可用的对象,可以调用实例方法
class Country{
    let name: String
    //这里加问号,表示City是optional,有值或者为空,因为phase 1阶段需要初始化所有属性,
    //所以city不加的话,就相当于没有完成第一阶段,所以不加就会报错,但是可以在确定有值得情况下,把?变成!
    var capitalCity: City?
    init(name: String,capitalName:String)
    {
        self.name=name
        self.capitalCity=City(name: capitalName, country: self)
    }
}

class City{
    let name:String
    unowned var country:Country
    init(name:String,country:Country) {
        self.name=name
        self.country=country
    }
}

Designated Initializer:构造函数

  • 至少有一个
  • 可以是自动生成的
  • 必须调用基类Designated Initializer
  • 最佳实践:Designated 尽可能少

Convenience Initializer

  • 便利的构造函数
  • 可有可无
  • 必须调用该类的Designated Initializer
convenience Initializer里面不能初始化自身的属性的,只能调用Designated Initializer

Failable Initializer:构造函数有可能失败

  • 返回Optional Value
  • 可以重载,可以重载成非Failable Initializer
Class TV{
 var model:String
//在这里需要将init变成optional类型,否则系统报错,需要明确这个返回类型。
init?(model:String){
 if model.isEmpty{
 return nil
}
self.model=model
}
}

//继承有可能为空的函数
//这里一定不会返回为空,
class SafeTV:TV{
  override init(model:String){
  if model.isEmpty{
//这里叹号表示不会运行失败,失败的话跑出运行时的异常,在编译的时候是可以通过的
  super.init(model:"old-man")!
}
else{
  super.init(model:model)!
}
}
}
image.png

相关文章

网友评论

      本文标题:类的构造和析构

      本文链接:https://www.haomeiwen.com/subject/rgfqkqtx.html