Swift - Inicialización
Las clases, estructuras y enumeraciones una vez declaradas en Swift 4 se inicializan para preparar la instancia de una clase. El valor inicial se inicializa para la propiedad almacenada y también para las nuevas instancias, los valores se inicializan para continuar. La palabra clave para crear la función de inicialización se lleva a cabo mediante el método 'init ()'. El inicializador Swift 4 difiere de Objective-C en que no devuelve ningún valor. Su función es verificar la inicialización de instancias recién creadas antes de su procesamiento. Swift 4 también proporciona un proceso de 'desinicialización' para realizar operaciones de administración de memoria una vez que se desasignan las instancias.
Rol de inicializador para propiedades almacenadas
La propiedad almacenada tiene que inicializar las instancias para sus clases y estructuras antes de procesar las instancias. Las propiedades almacenadas usan el inicializador para asignar e inicializar valores, erradicando así la necesidad de llamar a observadores de propiedades. El inicializador se usa en la propiedad almacenada
Para crear un valor inicial.
Para asignar un valor de propiedad predeterminado dentro de la definición de propiedad.
Para inicializar una instancia para un tipo de datos particular, se usa 'init ()'. No se pasan argumentos dentro de la función init ().
Sintaxis
init() {
//New Instance initialization goes here
}
Ejemplo
struct rectangle {
var length: Double
var breadth: Double
init() {
length = 6
breadth = 12
}
}
var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
area of rectangle is 72.0
Aquí, la estructura 'rectángulo' se inicializa con miembros de longitud y anchura como tipos de datos 'Doble'. El método Init () se utiliza para inicializar los valores de la longitud y el doble de los miembros recién creados. El área del rectángulo se calcula y se devuelve llamando a la función rectángulo.
Establecer valores de propiedad de forma predeterminada
El lenguaje Swift 4 proporciona la función Init () para inicializar los valores de propiedad almacenados. Además, el usuario tiene la posibilidad de inicializar los valores de propiedad de forma predeterminada mientras declara los miembros de la clase o estructura. Cuando la propiedad toma el mismo valor solo en todo el programa, podemos declararlo solo en la sección de declaración en lugar de inicializarlo en init (). Establecer valores de propiedad de forma predeterminada habilita al usuario cuando se define la herencia para clases o estructuras.
struct rectangle {
var length = 6
var breadth = 12
}
var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
area of rectangle is 72
Aquí, en lugar de declarar la longitud y la amplitud en init (), los valores se inicializan en la declaración misma.
Inicialización de parámetros
En el lenguaje Swift 4, el usuario tiene la posibilidad de inicializar parámetros como parte de la definición del inicializador usando init ().
struct Rectangle {
var length: Double
var breadth: Double
var area: Double
init(fromLength length: Double, fromBreadth breadth: Double) {
self.length = length
self.breadth = breadth
area = length * breadth
}
init(fromLeng leng: Double, fromBread bread: Double) {
self.length = leng
self.breadth = bread
area = leng * bread
}
}
let ar = Rectangle(fromLength: 6, fromBreadth: 12)
print("area is: \(ar.area)")
let are = Rectangle(fromLeng: 36, fromBread: 12)
print("area is: \(are.area)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
area is: 72.0
area is: 432.0
Parámetros locales y externos
Los parámetros de inicialización tienen nombres de parámetros locales y globales similares a los de los parámetros de función y método. La declaración de parámetro local se usa para acceder dentro del cuerpo de inicialización y la declaración de parámetro externo se usa para llamar al inicializador. Los inicializadores de Swift 4 difieren del inicializador de funciones y métodos en que no identifican qué inicializador se usa para llamar a qué funciones.
Para superar esto, Swift 4 introduce un nombre externo automático para todos y cada uno de los parámetros en init (). Este nombre externo automático es equivalente al nombre local escrito antes de cada parámetro de inicialización.
struct Days {
let sunday, monday, tuesday: Int
init(sunday: Int, monday: Int, tuesday: Int) {
self.sunday = sunday
self.monday = monday
self.tuesday = tuesday
}
init(daysofaweek: Int) {
sunday = daysofaweek
monday = daysofaweek
tuesday = daysofaweek
}
}
let week = Days(sunday: 1, monday: 2, tuesday: 3)
print("Days of a Week is: \(week.sunday)")
print("Days of a Week is: \(week.monday)")
print("Days of a Week is: \(week.tuesday)")
let weekdays = Days(daysofaweek: 4)
print("Days of a Week is: \(weekdays.sunday)")
print("Days of a Week is: \(weekdays.monday)")
print("Days of a Week is: \(weekdays.tuesday)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Days of a Week is: 1
Days of a Week is: 2
Days of a Week is: 3
Days of a Week is: 4
Days of a Week is: 4
Days of a Week is: 4
Parámetros sin nombres externos
Cuando no se necesita un nombre externo para un guión bajo de inicialización, se usa '_' para anular el comportamiento predeterminado.
struct Rectangle {
var length: Double
init(frombreadth breadth: Double) {
length = breadth * 10
}
init(frombre bre: Double) {
length = bre * 30
}
init(_ area: Double) {
length = area
}
}
let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
area is: 180.0
area is: 370.0
area is: 110.0
Tipos de propiedad opcionales
Cuando la propiedad almacenada en alguna instancia no devuelve ningún valor, esa propiedad se declara con un tipo "opcional" que indica que "no se devuelve ningún valor" para ese tipo en particular. Cuando la propiedad almacenada se declara como 'opcional', automáticamente inicializa el valor para que sea 'nulo' durante la inicialización.
struct Rectangle {
var length: Double?
init(frombreadth breadth: Double) {
length = breadth * 10
}
init(frombre bre: Double) {
length = bre * 30
}
init(_ area: Double) {
length = area
}
}
let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)
Modificación de propiedades constantes durante la inicialización
La inicialización también permite al usuario modificar el valor de la propiedad constante. Durante la inicialización, la propiedad de clase permite que sus instancias de clase sean modificadas por la superclase y no por la subclase. Considere, por ejemplo, que en el programa anterior 'longitud' se declara como 'variable' en la clase principal. La siguiente variable de programa 'longitud' se modifica como variable 'constante'.
struct Rectangle {
let length: Double?
init(frombreadth breadth: Double) {
length = breadth * 10
}
init(frombre bre: Double) {
length = bre * 30
}
init(_ area: Double) {
length = area
}
}
let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")
let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")
let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)
Inicializadores predeterminados
Los inicializadores predeterminados proporcionan una nueva instancia a todas sus propiedades declaradas de clase base o estructura con valores predeterminados.
class defaultexample {
var studname: String?
var stmark = 98
var pass = true
}
var result = defaultexample()
print("result is: \(result.studname)")
print("result is: \(result.stmark)")
print("result is: \(result.pass)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado. -
result is: nil
result is: 98
result is: true
El programa anterior se define con el nombre de clase como 'ejemplo predeterminado'. Tres funciones miembro se inicializan de forma predeterminada como 'studname?' para almacenar valores 'nil', 'stmark' como 98 y 'pass' como valor booleano 'true'. Asimismo, los valores de los miembros de la clase se pueden inicializar de forma predeterminada antes de procesar los tipos de miembros de la clase.
Inicializadores Memberwise para tipos de estructura
Cuando el usuario no proporciona los inicializadores personalizados, los tipos de estructura en Swift 4 recibirán automáticamente el 'inicializador de miembros'. Su función principal es inicializar las nuevas instancias de estructura con la inicialización de miembro por defecto y luego las propiedades de la nueva instancia se pasan a la inicialización de miembro por nombre.
struct Rectangle {
var length = 100.0, breadth = 200.0
}
let area = Rectangle(length: 24.0, breadth: 32.0)
print("Area of rectangle is: \(area.length)")
print("Area of rectangle is: \(area.breadth)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Area of rectangle is: 24.0
Area of rectangle is: 32.0
Las estructuras se inicializan de forma predeterminada para sus funciones de pertenencia durante la inicialización para 'longitud' como '100.0' y 'amplitud' como '200.0'. Pero los valores se anulan durante el procesamiento de las variables longitud y amplitud como 24.0 y 32.0.
Delegación de inicializador para tipos de valor
La delegación de inicializadores se define como la llamada a inicializadores desde otros inicializadores. Su función principal es actuar como reutilización para evitar la duplicación de código en varios inicializadores.
struct Stmark {
var mark1 = 0.0, mark2 = 0.0
}
struct stdb {
var m1 = 0.0, m2 = 0.0
}
struct block {
var average = stdb()
var result = Stmark()
init() {}
init(average: stdb, result: Stmark) {
self.average = average
self.result = result
}
init(avg: stdb, result: Stmark) {
let tot = avg.m1 - (result.mark1 / 2)
let tot1 = avg.m2 - (result.mark2 / 2)
self.init(average: stdb(m1: tot, m2: tot1), result: result)
}
}
let set1 = block()
print("student result is: \(set1.average.m1, set1.average.m2)
\(set1.result.mark1, set1.result.mark2)")
let set2 = block(average: stdb(m1: 2.0, m2: 2.0),
result: Stmark(mark1: 5.0, mark2: 5.0))
print("student result is: \(set2.average.m1, set2.average.m2)
\(set2.result.mark1, set2.result.mark2)")
let set3 = block(avg: stdb(m1: 4.0, m2: 4.0),
result: Stmark(mark1: 3.0, mark2: 3.0))
print("student result is: \(set3.average.m1, set3.average.m2)
\(set3.result.mark1, set3.result.mark2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
(0.0,0.0) (0.0,0.0)
(2.0,2.0) 5.0,5.0)
(2.5,2.5) (3.0,3.0)
Reglas para la delegación del inicializador
Tipos de valor | Tipos de clases |
---|---|
La herencia no se admite para tipos de valor como estructuras y enumeraciones. La referencia a otros inicializadores se realiza a través de self.init | Se admite la herencia. Comprueba que todos los valores de propiedad almacenados estén inicializados |
Herencia e inicialización de clases
Los tipos de clase tienen dos tipos de inicializadores para comprobar si las propiedades almacenadas definidas reciben un valor inicial, a saber, inicializadores designados e inicializadores de conveniencia.
Inicializadores designados e inicializadores de conveniencia
Inicializador designado | Inicializador de conveniencia |
---|---|
Considerado como inicializaciones primarias para una clase | Considerado como soporte de inicialización para una clase |
Todas las propiedades de la clase se inicializan y se llama al inicializador de superclase apropiado para una inicialización adicional | El inicializador designado se llama con un inicializador de conveniencia para crear una instancia de clase para un caso de uso específico o un tipo de valor de entrada |
Se define al menos un inicializador designado para cada clase | No es necesario tener definidos inicializadores de conveniencia obligatorios cuando la clase no requiere inicializadores. |
Init (parámetros) {declaraciones} | conveniencia init (parámetros) {declaraciones} |
Programa para inicializadores designados
class mainClass {
var no1 : Int // local storage
init(no1 : Int) {
self.no1 = no1 // initialization
}
}
class subClass : mainClass {
var no2 : Int // new subclass storage
init(no1 : Int, no2 : Int) {
self.no2 = no2 // initialization
super.init(no1:no1) // redirect to superclass
}
}
let res = mainClass(no1: 10)
let print = subClass(no1: 10, no2: 20)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
res is: 10
res is: 10
res is: 20
Programa para inicializadores de conveniencia
class mainClass {
var no1 : Int // local storage
init(no1 : Int) {
self.no1 = no1 // initialization
}
}
class subClass : mainClass {
var no2 : Int
init(no1 : Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// Requires only one parameter for convenient method
override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
res is: 20
res is: 30
res is: 50
Herencia y anulación del inicializador
Swift 4 no permite que sus subclases hereden sus inicializadores de superclase para sus tipos de miembros de forma predeterminada. La herencia es aplicable a los inicializadores Superclase solo hasta cierto punto, lo que se discutirá en Herencia del inicializador automático.
Cuando el usuario necesita tener inicializadores definidos en superclase, el usuario debe definir una subclase con inicializadores como implementación personalizada. Cuando la subclase debe realizar la anulación a la superclase, se debe declarar la palabra clave 'anular'.
class sides {
var corners = 4
var description: String {
return "\(corners) sides"
}
}
let rectangle = sides()
print("Rectangle: \(rectangle.description)")
class pentagon: sides {
override init() {
super.init()
corners = 5
}
}
let bicycle = pentagon()
print("Pentagon: \(bicycle.description)")
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Rectangle: 4 sides
Pentagon: 5 sides
Inicializadores designados y convenientes en acción
class Planet {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[No Planets]")
}
}
let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")
let noplName = Planet()
print("No Planets like that: \(noplName.name)")
class planets: Planet {
var count: Int
init(name: String, count: Int) {
self.count = count
super.init(name: name)
}
override convenience init(name: String) {
self.init(name: name, count: 1)
}
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Planet name is: Mercury
No Planets like that: [No Planets]
Inicializador fallido
El usuario debe ser notificado cuando haya fallas en el inicializador al definir una clase, estructura o valores de enumeración. La inicialización de variables a veces se convierte en una falla debido a:
- Valores de parámetro no válidos.
- Ausencia de fuente externa requerida.
- Condición que impide que la inicialización se realice correctamente.
Para detectar las excepciones generadas por el método de inicialización, Swift 4 produce una inicialización flexible llamada 'inicializador fallido' para notificar al usuario que algo pasa desapercibido al inicializar la estructura, clase o miembros de enumeración. La palabra clave para detectar el inicializador fallido es 'init?'. Además, los inicializadores fallidos y no fallidos no se pueden definir con los mismos tipos y nombres de parámetros.
struct studrecord {
let stname: String
init?(stname: String) {
if stname.isEmpty {return nil }
self.stname = stname
}
}
let stmark = studrecord(stname: "Swing")
if let name = stmark {
print("Student name is specified")
}
let blankname = studrecord(stname: "")
if blankname == nil {
print("Student name is left blank")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Student name is specified
Student name is left blank
Inicializadores fallidos para enumeraciones
El lenguaje Swift 4 proporciona la flexibilidad de tener inicializadores Failable para enumeraciones también para notificar al usuario cuando los miembros de la enumeración quedan sin inicializar valores.
enum functions {
case a, b, c, d
init?(funct: String) {
switch funct {
case "one":
self = .a
case "two":
self = .b
case "three":
self = .c
case "four":
self = .d
default:
return nil
}
}
}
let result = functions(funct: "two")
if result != nil {
print("With In Block Two")
}
let badresult = functions(funct: "five")
if badresult == nil {
print("Block Does Not Exist")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
With In Block Two
Block Does Not Exist
Inicializadores fallidos para clases
Un inicializador que falla cuando se declara con enumeraciones y estructuras alerta de una falla de inicialización en cualquier circunstancia dentro de su implementación. Sin embargo, el inicializador que falla en las clases alertará sobre la falla solo después de que las propiedades almacenadas se hayan establecido en un valor inicial.
class studrecord {
let studname: String!
init?(studname: String) {
self.studname = studname
if studname.isEmpty { return nil }
}
}
if let stname = studrecord(studname: "Failable Initializers") {
print("Module is \(stname.studname)")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Module is Optional("Failable Initializers")
Anulación de un inicializador fallido
Al igual que en el caso de inicializar, el usuario también tiene la posibilidad de anular un inicializador fallido de superclase dentro de la subclase. La inicialización fallida de superclase también se puede anular con un inicializador no fallido de subclase.
El inicializador de subclase no puede delegar hasta el inicializador de superclase cuando se reemplaza un inicializador de superclase que falla con una inicialización de subclase que no falla.
Un inicializador que no falla nunca puede delegar en un inicializador que falla.
El programa que se proporciona a continuación describe los inicializadores fallidos y no fallidos.
class Planet {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[No Planets]")
}
}
let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")
let noplName = Planet()
print("No Planets like that: \(noplName.name)")
class planets: Planet {
var count: Int
init(name: String, count: Int) {
self.count = count
super.init(name: name)
}
override convenience init(name: String) {
self.init(name: name, count: 1)
}
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Planet name is: Mercury
No Planets like that: [No Planets]
El init! Inicializador fallido
Swift 4 proporciona 'init?' para definir un inicializador fallable de instancia opcional. Para definir una instancia opcional implícitamente desenvuelta del tipo específico 'init!' está especificado.
struct studrecord {
let stname: String
init!(stname: String) {
if stname.isEmpty {return nil }
self.stname = stname
}
}
let stmark = studrecord(stname: "Swing")
if let name = stmark {
print("Student name is specified")
}
let blankname = studrecord(stname: "")
if blankname == nil {
print("Student name is left blank")
}
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
Student name is specified
Student name is left blank
Inicializadores requeridos
Para declarar todas y cada una de las subclases de la palabra clave initialize 'required' debe definirse antes de la función init ().
class classA {
required init() {
var a = 10
print(a)
}
}
class classB: classA {
required init() {
var b = 30
print(b)
}
}
let res = classA()
let print = classB()
Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:
10
30
10