Swift 调用静态方法:type(of: self) vs 显式类名 [英] Swift calling static methods: type(of: self) vs explicit class name

查看:63
本文介绍了Swift 调用静态方法:type(of: self) vs 显式类名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 swift 中,实例 func 不能调用 static/class func 而不用类名作为方法调用的前缀.或者你可以使用 type(of: self),例如

In swift, an instance func can't call a static/class func without prefixing the method call with the class name. OR you can use type(of: self), e.g

class Foo {
    static func doIt() { }

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

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

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

My question is, what's the difference here? Is it just a matter of coding style, or is there some difference e.g. static or dynamic dispatch going on?

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

If it is just coding style, what's the preferred style?

推荐答案

有两个主要区别.

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

The metatype that you call the static method on is available to you in the method as self (it's simply passed as an implicit parameter). Therefore if you call doIt() on type(of: self), self will be the dynamic metatype of the instance. If you call it on Foo, self will be 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

这种差异对于工厂方法确实很重要,因为它决定了您创建的实例的类型.

This difference can be really important for factory methods, as it determines the type of instance you create.

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 已经介绍了这一点,但我想我会为了完成而添加它.)

2. The dispatching of the static method

(Martin has already covered this, but I thought I would add it for the sake of completion.)

对于在子类中重写的 class 方法,您调用该方法的元类型的值决定了要调用的实现.

For class methods that are overridden in subclasses, the value of the metatype that you call the method on determines which implementation to call.

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

If called on a metatype that is known at compile time (e.g Foo.doIt()), Swift is able to statically dispatch the call. However, if you call the method on a metatype that isn't known until runtime (e.g type(of: self)), the method call will be dynamically dispatched to the correct implementation for the metatype value.

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

这篇关于Swift 调用静态方法:type(of: self) vs 显式类名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆