tipos programacion parametros parametro opcional metodos funciones for externos datos class static swift

class - programacion - ¿Cuál es la diferencia entre función estática y función de clase en Swift?



tipos de datos en swift (7)

Puedo ver estas definiciones en la biblioteca de Swift:

extension Bool : BooleanLiteralConvertible { static func convertFromBooleanLiteral(value: Bool) -> Bool } protocol BooleanLiteralConvertible { typealias BooleanLiteralType class func convertFromBooleanLiteral(value: BooleanLiteralType) -> Self }

¿Cuál es la diferencia entre una función miembro definida como static func y otra definida como class func ? ¿Es simplemente que static es para funciones estáticas de estructuras y enumeraciones, y class para clases y protocolos? ¿Hay alguna otra diferencia que uno deba saber? ¿Cuál es la razón para tener esta distinción en la propia sintaxis?


¿Es simplemente que estático es para funciones estáticas de estructuras y enumeraciones, y clase para clases y protocolos?

Esa es la principal diferencia. Algunas otras diferencias son que las funciones de clase se distribuyen dinámicamente y pueden ser reemplazadas por subclases.

Los protocolos utilizan la palabra clave de clase, pero no excluyen las estructuras de la implementación del protocolo, en su lugar solo usan estática. La clase se eligió para los protocolos, por lo que no tendría que haber una tercera palabra clave para representar estática o clase.

De Chris Lattner sobre este tema:

Consideramos la posibilidad de unificar la sintaxis (por ejemplo, usar "tipo" como palabra clave), pero eso no es realmente simple. Las palabras clave "clase" y "estática" son buenas para la familiaridad y son bastante descriptivas (una vez que entiendes cómo funcionan los métodos +), y abres la puerta para agregar métodos verdaderamente estáticos a las clases. La rareza principal de este modelo es que los protocolos tienen que elegir una palabra clave (y nosotros elegimos "clase"), pero en general es la compensación correcta.

Y aquí hay un fragmento que muestra algunos de los comportamientos de anulación de las funciones de clase:

class MyClass { class func myFunc() { println("myClass") } } class MyOtherClass: MyClass { override class func myFunc() { println("myOtherClass") } } var x: MyClass = MyOtherClass() x.dynamicType.myFunc() //myOtherClass x = MyClass() x.dynamicType.myFunc() //myClass


Para declarar una propiedad de variable de tipo, marque la declaración con el modificador de declaración static . Las clases pueden marcar propiedades computadas de tipo con el modificador de declaración de class lugar de permitir que las subclases anulen la implementación de la superclase. Las propiedades de tipo se discuten en Propiedades de tipo.

NOTA
En una declaración de clase, la palabra clave static tiene el mismo efecto que marcar la declaración con los modificadores de declaración final y de class .

Fuente: El lenguaje de programación Swift - Propiedades de tipo variable


Desde Swift2.0, Apple dice:

"Siempre prefije los requisitos de propiedad de tipo con la palabra clave estática cuando los defina en un protocolo. Esta regla se aplica a pesar de que los requisitos de propiedad de tipo pueden tener el prefijo de la clase o la palabra clave estática cuando la implementa una clase:"


Hice algunos experimentos en el patio y obtuve algunas conclusiones.

TL; DR

Como puede ver, en el caso de la class , el uso de class func de class func o static func es solo una cuestión de hábito.

Ejemplo de patio de recreo con explicación:

class Dog { final func identity() -> String { return "Once a woofer, forever a woofer!" } class func talk() -> String { return "Woof woof!" } static func eat() -> String { return "Miam miam" } func sleep() -> String { return "Zzz" } } class Bulldog: Dog { // Can not override a final function // override final func identity() -> String { // return "I''m once a dog but now I''m a cat" // } // Can not override a "class func", but redeclare is ok func talk() -> String { return "I''m a bulldog, and I don''t woof." } // Same as "class func" func eat() -> String { return "I''m a bulldog, and I don''t eat." } // Normal function can be overridden override func sleep() -> String { return "I''m a bulldog, and I don''t sleep." } } let dog = Dog() let bullDog = Bulldog() // FINAL FUNC //print(Dog.identity()) // compile error print(dog.identity()) // print "Once a woofer, forever a woofer!" //print(Bulldog.identity()) // compile error print(bullDog.identity()) // print "Once a woofer, forever a woofer!" // => "final func" is just a "normal" one but prevented to be overridden nor redeclared by subclasses. // CLASS FUNC print(Dog.talk()) // print "Woof woof!", called directly from class //print(dog.talk()) // compile error cause "class func" is meant to be called directly from class, not an instance. print(Bulldog.talk()) // print "Woof woof!" cause it''s called from Bulldog class, not bullDog instance. print(bullDog.talk()) // print "I''m a bulldog, and I don''t woof." cause talk() is redeclared and it''s called from bullDig instance // => "class func" is like a "static" one, must be called directly from class or subclassed, can be redeclared but NOT meant to be overridden. // STATIC FUNC print(Dog.eat()) // print "Miam miam" //print(dog.eat()) // compile error cause "static func" is type method print(Bulldog.eat()) // print "Miam miam" print(bullDog.eat()) // print "I''m a bulldog, and I don''t eat." // NORMAL FUNC //print(Dog.sleep()) // compile error print(dog.sleep()) // print "Zzz" //print(Bulldog.sleep()) // compile error print(bullDog.sleep()) // print "I''m a bulldog, and I don''t sleep."


La principal diferencia es que las estructuras son tipos de valor y las clases son tipos de referencia.

Cuando hace una copia de un tipo de valor, copia todos los datos de lo que está copiando en la nueva variable. Son 2 cosas separadas y cambiar una no afecta a la otra.

Cuando hace una copia de un tipo de referencia, la nueva variable se refiere a la misma ubicación de memoria que está copiando. Esto significa que cambiar uno cambiará al otro ya que ambos se refieren a la misma ubicación de memoria


Para ser más claros, hago un ejemplo aquí,

class ClassA { class func func1() -> String { return "func1" } static func func2() -> String { return "func2" } /* same as above final class func func2() -> String { return "func2" } */ }

static func es la misma que final class func

Debido a que es final , no podemos anularlo en la subclase de la siguiente manera:

class ClassB : ClassA { override class func func1() -> String { return "func1 in ClassB" } // ERROR: Class method overrides a ''final` class method override static func func2() -> String { return "func2 in ClassB" } }


Según el libro Swift 2.2 publicado por apple:

“Usted indica los métodos de tipo escribiendo la palabra clave static antes de la palabra clave func del método. Las clases también pueden usar la palabra clave de class para permitir que las subclases anulen la implementación de ese método por la superclase ".