swift - studio - Métodos estáticos de llamada rápida: tipo(de: auto) vs nombre de clase explícito
visual studio windows 7 (2)
Hay dos diferencias principales.
1. El valor del self
dentro del método estático.
El metatipo en el que llama al método estático está disponible en el método como self
(simplemente se pasa como un parámetro implícito). Por lo tanto, si llama a doIt()
en type(of: self)
, self
será el metatipo dinámico de la instancia. Si lo llamas en Foo
, el self
será 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
Esta diferencia puede ser realmente importante para los métodos de fábrica, ya que determina el tipo de instancia que crea.
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. El envío del método estático.
( Martin ya ha cubierto esto, pero pensé que lo agregaría para completar ) .
Para class
métodos de class
que se sobrescriben en las subclases, el valor del metatipo al que llama el método determina a qué implementación llamar.
Si se llama en un metatipo que se conoce en el momento de la compilación (por ejemplo, Foo.doIt()
), Swift puede enviar la llamada de forma estática. Sin embargo, si llama al método en un metatipo que no se conoce hasta el tiempo de ejecución (por ejemplo, type(of: self)
), la llamada al método se enviará dinámicamente a la implementación correcta para el valor de metatype.
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
En swift, una func
instancia no puede llamar a una función static/class func
sin prefijar la llamada al método con el nombre de la clase. O puedes usar type(of: self)
, por ejemplo
class Foo {
static func doIt() { }
func callIt() {
Foo.doIt() // This works
type(of: self).doIt() // Or this
doIt() // This doesn''t compile (unresolved identifier)
}
}
Mi pregunta es, ¿cuál es la diferencia aquí? ¿Es solo una cuestión de estilo de codificación, o hay alguna diferencia, por ejemplo, el envío estático o dinámico?
Si es solo un estilo de codificación, ¿cuál es el estilo preferido?
Para un método de class
hace una diferencia si el método se invalida en una subclase:
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
Esto también se documenta en "Types" en la Referencia del lenguaje Swift:
Puede usar una expresión de
type(of:)
con una instancia de un tipo para acceder al tipo de tiempo de ejecución dinámico de la instancia, como un valor, ...
No sé la diferencia de un método Corrección: vea la respuesta de Hamish para ver la diferencia entre los métodos estáticos y de clase. static
(que es final
y no se puede anular en una subclase).