Swift Propiedades

Las propiedades de Swift asocian valores con una clase, estructura o enumeración específica.

Las propiedades se pueden dividir en propiedades almacenadas y propiedades computadas:

Propiedades almacenadas Propiedades computadas
Almacenan constantes o variables como parte de una instancia. Calculan (en lugar de almacenar) un valor.
Se usan en clases y estructuras. Se usan en clases, estructuras y enumeraciones.

Las propiedades almacenadas y computadas se usan normalmente en instancias de un tipo específico.

Las propiedades también pueden usarse directamente en el propio tipo; estas propiedades se denominan propiedades de tipo.

Además, se pueden definir observadores de propiedades para monitorear los cambios en el valor de una propiedad y así desencadenar una operación personalizada. Los observadores de propiedades se pueden añadir a propiedades almacenadas escritas por uno mismo, así como a propiedades heredadas de una superclase.


Propiedades almacenadas

En pocas palabras, una propiedad almacenada es una constante o variable almacenada en una instancia de una clase o estructura específica.

Las propiedades almacenadas pueden ser propiedades almacenadas variables (definidas con la palabra clave `var`) o propiedades almacenadas constantes (definidas con la palabra clave `let`).

  • Se puede especificar un valor predeterminado al definir una propiedad almacenada.

  • También se puede establecer o modificar el valor de una propiedad almacenada durante el proceso de construcción, incluso modificar el valor de una propiedad almacenada constante.

import Cocoa

struct Number
{
   var digits: Int
   let pi = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.pi)")

El resultado de ejecutar el programa anterior es:

67
3.1415

Considera el siguiente código:

let pi = 3.1415

En el código, `pi` especifica un valor predeterminado (`pi = 3.1415`) al definir la propiedad almacenada, por lo que no cambiará sin importar cuándo instancies la estructura.

Si defines una propiedad almacenada constante e intentas modificarla, se producirá un error, como se muestra a continuación:

import Cocoa

struct Number
{
    var digits: Int
    let numbers = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7

El programa anterior dará un error al ejecutarse; el error es el siguiente:

error: cannot assign to property: 'numbers' is a 'let' constant
n.numbers = 8.7

Significa que 'numbers' es una constante y no puedes modificarla.


Propiedades almacenadas perezosas

Una propiedad almacenada perezosa es aquella cuyo valor inicial se calcula solo cuando se accede a ella por primera vez.

Antes de la declaración de la propiedad se usalazy`lazy` para marcar una propiedad almacenada perezosa.

Nota:
Debes declarar las propiedades almacenadas perezosas como variables (usando la palabra clavevar`var`), porque el valor de la propiedad puede no obtenerse hasta que se complete la construcción de la instancia. Mientras que una propiedad constante debe tener un valor inicial antes de que se complete el proceso de construcción, por lo tanto no se puede declarar como propiedad perezosa.

Las propiedades almacenadas perezosas generalmente se usan para:

  • Retrasar la creación de objetos.

  • Cuando el valor de la propiedad depende de otras clases desconocidas.

import Cocoa

class sample {
    lazy var no = number() // `var` 关键字是必须的
}

class number {
    var name = "Ejemplo Swift 教程"
}

var firstsample = sample()
print(firstsample.no.name)

El resultado de ejecutar el programa anterior es:

Ejemplo Swift 教程

Variables de instancia

Si tiene experiencia con Objective-C, debe saber que Objective-C proporciona dos métodos para que las instancias de clase almacenen valores y referencias. Para las propiedades, también se pueden usar variables de instancia como almacenamiento interno del valor de la propiedad.

En el lenguaje de programación Swift, estas teorías se unifican e implementan con propiedades. Las propiedades en Swift no tienen variables de instancia correspondientes, y el almacenamiento interno de la propiedad no se puede acceder directamente. Esto evita la confusión de diferentes modos de acceso en distintos escenarios y al mismo tiempo simplifica la definición de una propiedad a una sola declaración.

Toda la información de una propiedad en un tipo, incluyendo nombre, tipo y características de gestión de memoria, se define en un único lugar (en la definición del tipo).


Propiedades computadas

Además de las propiedades almacenadas, las clases, estructuras y enumeraciones pueden definirpropiedades computadas, las cuales no almacenan valores directamente, sino que proporcionan un getter para obtener el valor y un setter opcional para establecer indirectamente el valor de otras propiedades o variables.

import Cocoa

class sample {
    var no1 = 0.0, no2 = 0.0
    var length = 300.0, breadth = 150.0
    
    var middle: (Double, Double) {
        get{
            return (length / 2, breadth / 2)
        }
        set(axis){
            no1 = axis.0 - (length / 2)
            no2 = axis.1 - (breadth / 2)
        }
    }
}

var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)

print(result.no1)
print(result.no2)

El resultado de ejecutar el programa anterior es:

(150.0, 75.0)
-150.0
-65.0

Si el setter de una propiedad computada no define el nombre del parámetro para el nuevo valor, se puede usar el nombre predeterminado `newValue`.


Propiedades computadas de solo lectura

Una propiedad computada que solo tiene getter y no tiene setter es una propiedad computada de solo lectura.

Las propiedades computadas de solo lectura siempre devuelven un valor; se pueden acceder mediante el operador punto (.), pero no se puede establecer un nuevo valor.

import Cocoa

class film {
    var head = ""
    var duration = 0.0
    var metaInfo: [String:String] {
        return [
            "head": self.head,
            "duration":"\(self.duration)"
        ]
    }
}

var movie = film()
movie.head = "Swift 属性"
movie.duration = 3.09

print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)

El resultado de ejecutar el programa anterior es:

Swift 属性
3.09

Nota:

Debe usarse la palabra clavevar`var` para definir propiedades computadas, incluidas las de solo lectura, porque sus valores no son fijos.let`let` solo se usa para declarar propiedades constantes, lo que significa que el valor no se puede modificar después de la inicialización.


Observadores de propiedades

Los observadores de propiedades monitorean y responden a los cambios en el valor de una propiedad. Cada vez que se establece un valor para la propiedad, se llama a los observadores de propiedades, incluso cuando el nuevo valor es igual al valor actual.

Se pueden agregar observadores de propiedades a otras propiedades almacenadas además de las propiedades almacenadas perezosas, y también se pueden agregar a propiedades heredadas (incluyendo propiedades almacenadas y computadas) mediante la sobreescritura de la propiedad.

Nota:
No es necesario agregar observadores de propiedades a las propiedades computadas que no se pueden sobreescribir, porque se pueden monitorear y responder a los cambios de valor directamente a través del setter.

Se pueden agregar uno o todos los siguientes observadores a una propiedad:

  • willSetSe llama antes de establecer el nuevo valor.
  • didSetSe llama inmediatamente después de que el nuevo valor haya sido establecido.
  • Los observadores `willSet` y `didSet` no se llaman durante la inicialización de la propiedad.
import Cocoa

class Samplepgm {
    var counter: Int = 0{
        willSet(newTotal){
            print("计数器: \(newTotal)")
        }
        didSet{
            if counter > oldValue {
                print("新增数 \(counter - oldValue)")
            }
        }
    }
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

El resultado de ejecutar el programa anterior es:

计数器: 100
新增数 100
计数器: 800
新增数 700

Variables globales y locales

Los patrones descritos para las propiedades computadas y los observadores de propiedades también se pueden aplicar a variables globales y locales.

Variables locales Variables globales
Variables definidas dentro de una función, método o cierre. Variables definidas fuera de cualquier función, método, cierre o tipo.
Se usan para almacenar y recuperar valores. Se usan para almacenar y recuperar valores.
Las propiedades almacenadas se usan para obtener y establecer valores. Las propiedades almacenadas se usan para obtener y establecer valores.
También se usan para propiedades computadas. También se usan para propiedades computadas.

Propiedades de tipo

Las propiedades de tipo se escriben como parte de la definición del tipo, dentro de las llaves ({}) más externas del tipo.

Use la palabra clave `static` para definir propiedades de tipo de tipos de valor, y la palabra clave `class` para definir propiedades de tipo para clases.

struct Structname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // 这里返回一个 Int 值
   }
}

enum Enumname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // 这里返回一个 Int 值
   }
}

class Classname {
   class var computedTypeProperty: Int {
      // 这里返回一个 Int 值
   }
}

Nota:
En el ejemplo, las propiedades de tipo computadas son de solo lectura, pero también se pueden definir propiedades de tipo computadas de lectura y escritura, con una sintaxis similar a la de las propiedades computadas de instancia.


Obtener y establecer el valor de las propiedades de tipo

De manera similar a las propiedades de instancia, el acceso a las propiedades de tipo se realiza mediante el operador punto (.). Sin embargo, las propiedades de tipo se obtienen y establecen a través del propio tipo, no a través de una instancia. Ejemplo:

import Cocoa

struct StudMarks {
   static let markCount = 97
   static var totalCount = 0
   var InternalMarks: Int = 0 {
      didSet {
         if InternalMarks > StudMarks.markCount {
            InternalMarks = StudMarks.markCount
         }
         if InternalMarks > StudMarks.totalCount {
            StudMarks.totalCount = InternalMarks
         }
      }
   }
}

var stud1Mark1 = StudMarks()
var stud1Mark2 = StudMarks()

stud1Mark1.InternalMarks = 98
print(stud1Mark1.InternalMarks) 

stud1Mark2.InternalMarks = 87
print(stud1Mark2.InternalMarks)

El resultado de ejecutar el programa anterior es:

97
87
Otras extensiones