swifter-tips / Public-Issues

Public issues for Swifter-tips book

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

关于第17个tip “初始化方法顺序” 疑惑

zyg-github opened this issue · comments

commented

原文:
“这种情况下,Swift 会自动地对父类的对应 init 方法进行调用,也就是说,第 2 步的 super.init() 也是可以不用写的 (但是实际上还是调用的,只不过是为了简便 Swift 帮我们完成了)。”

我试验了一下 按照你的例子是没有错

但是如果 (把 init() 修改为 init(t:Int) )
class Cat1 {
var name: String
init(t:Int) {
name = "cat"
}
}

class Tiger1: Cat1 {
let power: Int
override init(t:Int) {
power = 10
super.init(t: t)
//需要手动调用 super.init(t: t)
}
}

所以我觉得 编译器 只会帮你自动调用 super.init()(默认的初始化方法) 但其他的 非默认的init 是不会自动调用的

不知道对不对? 请大神指点一下

对的,至少从表象上看是这样的。

对于不带参数的版本,在转换为 SIL (Swift Intermediate Language) 的时候编译器前端为我们拿到了 super 的 init 然后进行了调用:

// main.Tiger.init (main.Tiger.Type)() -> main.Tiger
sil hidden @_TFC4main5TigercfMS0_FT_S0_ : $@convention(method) (@owned Tiger) -> @owned Tiger {
bb0(%0 : $Tiger):
  %1 = alloc_stack $Tiger  // let self            // users: %2, %10, %13, %14
  store %0 to %1#1 : $*Tiger                      // id: %2
  %3 = integer_literal $Builtin.Int64, 10         // user: %4
  %4 = struct $Int (%3 : $Builtin.Int64)          // user: %6
  %5 = ref_element_addr %0 : $Tiger, #Tiger.power // user: %6
  store %4 to %5 : $*Int                          // id: %6
  %7 = upcast %0 : $Tiger to $Cat                 // user: %11
  // function_ref main.Cat.init (main.Cat.Type)() -> main.Cat
  %8 = function_ref @_TFC4main3CatcfMS0_FT_S0_ : $@convention(method) (@owned Cat) -> @owned Cat // user: %11
  %9 = null_class $Tiger                          // user: %10
  store %9 to %1#1 : $*Tiger                      // id: %10
  %11 = apply %8(%7) : $@convention(method) (@owned Cat) -> @owned Cat // user: %12
  %12 = unchecked_ref_cast %11 : $Cat to $Tiger   // users: %13, %15
  store %12 to %1#1 : $*Tiger                     // id: %13
  dealloc_stack %1#0 : $*@local_storage Tiger     // id: %14
  return %12 : $Tiger                             // id: %15
}

但是对于有参数的版本并没有自动添加。这个应该是编译器实现的一个细节(当然这需要等开源以后才能确认了)。在技术原理上来说是可以实现的(因为 init 方法的第一个参数默认是带有参数名字的,在 override 的时候总能找到父类中的方法)。现在猜测的话,但是编译器并不能替你做主,因为它不知道这个参数的意义,或者你是不是希望原封不动地传入向 super 传入这个参数,但是对于无参数版本就没有这个顾虑。

commented

确实 对于 有参数的init 不应该有自动调用 super的init 因为无法确认 你传人super init 的参数
谢谢 喵神~