Swift调用静态方法:type(of:self)vs explicit class name

时间:2017-02-15 21:24:54

标签: swift static-methods

在swift中,实例func无法调用static/class func,而无需使用类名为方法调用添加前缀。或者您可以使用type(of: self),例如

class Foo {
    static func doIt() { }

    func callIt() {
        Foo.doIt() // This works
        type(of: self).doIt() // Or this

        doIt() // This doesn't compile (unresolved identifier)
    }
}

我的问题是,这里的区别是什么? 这仅仅是编码风格的问题,还是存在一些差异,例如:静态或动态调度正在进行?

如果它只是编码风格,那么首选风格是什么?

2 个答案:

答案 0 :(得分:27)

有两个主要区别。

1。静态方法

self的值

您在方法中可以使用调用静态方法的元类型self(它只是作为隐式参数传递)。因此,如果您在type(of: self)上致电doIt()self将成为该实例的动态元类型。如果您在Foo上致电,self将为Foo.self

class Foo {
    static func doIt() {
        print("hey I'm of type \(self)")
    }

    func callDoItOnDynamicType() {
        type(of: self).doIt() // call on the dynamic metatype of the instance.
    }

    func classDoItOnFoo() {
        Foo.doIt() // call on the metatype Foo.self.
    }
}

class Bar : Foo {}

let f: Foo = Bar()

f.callDoItOnDynamicType() // hey I'm of type Bar
f.classDoItOnFoo()        // hey I'm of type Foo

对于工厂方法,这种差异可能非常,因为它决定了您创建的实例的类型。

class Foo {
    required init() {}

    static func create() -> Self {
        return self.init()
    }

    func createDynamic() -> Foo {
        return type(of: self).create()
    }

    func createFoo() -> Foo {
        return Foo.create()
    }
}

class Bar : Foo {}

let f: Foo = Bar()

print(f.createDynamic()) // Bar
print(f.createFoo())     // Foo

2。调度静态方法

Martin has already covered这个,但我想我会为了完成而添加它。

对于在子类中重写的class方法,调用方法on的元类型的值确定要调用的实现。

如果在编译时已知的元类型(例如Foo.doIt())上调用,则Swift能够静态调度该调用。但是,如果在运行时已知的元类型上调用方法(例如type(of: self)),则方法调用将动态分派给元类型值的正确实现

class Foo {
    class func doIt() {
        print("Foo's doIt")
    }

    func callDoItOnDynamicType() {
        type(of: self).doIt() // the call to doIt() will be dynamically dispatched.
    }

    func classDoItOnFoo() {
        Foo.doIt() // will be statically dispatched.
    }
}


class Bar : Foo {
    override class func doIt() {
        print("Bar's doIt")
    }
}

let f: Foo = Bar()

f.callDoItOnDynamicType() // Bar's doIt
f.classDoItOnFoo()        // Foo's doIt

答案 1 :(得分:4)

对于class方法,如果方法是,则会有所不同 在子类中重写:

class Foo {
    class func doIt() {
        print("Foo doit")
    }

    func callViaClassname() {
        Foo.doIt()
    }

    func callViaTypeOf() {
        type(of: self).doIt()
    }
}

class Bar: Foo {
    override class func doIt() {
        print("Bar doit")
    }

}

Bar().callViaClassname() // Foo doit
Bar().callViaTypeOf() // Bar doit

Swift语言参考中的"Types"中也记录了这一点:

  

您可以使用type(of:)表达式和类型实例来访问该实例的动态,运行时类型作为值,...

我不知道static方法的区别(final 并且不能在子类中重写。 更正:有关差异,请参阅Hamish's answer 在静态和类方法中。