只有15%的iOS开发者答对的一道题,你的答案呢?

139 阅读1分钟

代码是这样的,你先自己猜测一下下面的代码会输出什么

class A {
    func f(value: Int = 10) {
        print("A: \(value)")
    }
}

class B: A {
    override func f(value: Int = 100) {
        print("B: \(value)")
    }
}

let b: A = B()
b.f()
  1. “B: 100”
  2. “A: 100”
  3. “B: 10”
  4. “A: 10”

上面的代码实际上包含两大机制

对象方法的实现是动态决议,它取决于运行时对象的实际类型

  1. 我们知道Swift中的方法派发有三种,分别是静态派发、动态派发、消息发送机制
  2. 类里面方法的派发默认是动态派发,调用时通过从函数表里找方法地址,然后跳转执行
  3. 类的函数表类似于C++的虚函数表,每个类有一份,对于重写的方法,子类方法表里的地址也会替换父类方法表里的地址
  4. b这个实例编译时是A类型,但运行时实际是B类型。所以会走到B这个类的函数表里,调用的f方法也是B里的实现

方法的默认参数是静态决议,它取决于变量在编译时的类型

  1. 方法f的默认参数value,它的值取决于编译时。
  2. 又由于继承关系的存在,A类必然先编译,从而就决定了f的默认参数value的值是10

答案:最终的结果会同时包含动态决议的方法实现以及静态决议的参数默认值。所以答案是 3. "B: 10"

教训:当使用类时,要小心为参数提供默认值!最好不提供

资料

www.swiftwithvincent.com/newsletter/…