Latest web development tutorials

processus de construction Swift

Le processus de construction est d'utiliser une instance d'une classe, la structure ou le type d'énumération effectué le processus de préparation. Ce processus implique la définition des valeurs initiales pour chaque attribut et l'instance pour la préparation et l'exécution des tâches d'initialisation nécessaires.

méthode Swift constructeur init ().

Et Objective-C dans le constructeur différent, le constructeur Swift n'a pas besoin de retourner une valeur, leur tâche principale est de veiller à ce que la nouvelle instance est terminée avant la première utilisation de l'initialisation correcte.

Les instances de classes peuvent être définies destructor mémoire (deinitializer) Les travaux de nettoyage avant instance de classe est libéré.


L'affectation initiale de la propriété type de stockage

Les classes et les structures lorsqu'une instance est créée, elle doit définir la valeur initiale appropriée pour tous les attributs de type de stockage.

Lors du stockage de cession de la propriété dans le constructeur, leurs valeurs sont définies directement et ne déclenchent pas tout observateur de la propriété.

processus d'attribution de la propriété de stockage dans le constructeur:

  • Création de la valeur initiale.

  • Dans la définition de l'attribut spécifie les valeurs de propriété par défaut.

  • Initialise une instance, et appelle la méthode init ().


constructeur

Le constructeur est appelé lorsque vous créez une nouvelle instance d'un type particulier. Sa forme la plus simple est similaire à une méthode d'instance sans aucun paramètre, le nom de init mot-clé.

grammaire

init()
{
    // 实例化后执行的代码
}

Exemples

La structure suivante définit init un constructeur sans arguments, et à l'intérieur de la longueur de l'attribut type de stockage et la largeur de la valeur d'initialisation de 6 et 12:

struct rectangle {
    var length: Double
    var breadth: Double
    init() {
        length = 6
        breadth = 12
    }
}
var area = rectangle()
print("矩形面积为 \(area.length*area.breadth)")

La sortie de l'exécution du programme ci-dessus est la suivante:

矩形面积为 72.0

Les valeurs de propriété par défaut

Nous pouvons définir les valeurs initiales de la propriété type de stockage dans le constructeur; aussi, peut définir une valeur par défaut lorsque une déclaration de propriété.

Il vous permet d'utiliser le nettoyeur de constructeur par défaut, plus claire et peut automatiquement déduite par l'attribut type de valeur par défaut.

L'exemple suivant, nous voulons définir la valeur par défaut quand une déclaration de propriété:

struct rectangle {
	// 设置默认值
    var length = 6
    var breadth = 12
}
var area = rectangle()
print("矩形的面积为 \(area.length*area.breadth)")

La sortie de l'exécution du programme ci-dessus est la suivante:

矩形面积为 72

Paramètres de configuration

Vous pouvez définir le constructeur à condition que le paramètre du constructeur init (), comme suit:

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("面积为: \(ar.area)")

let are = Rectangle(fromLeng: 36, fromBread: 12)
print("面积为: \(are.area)")

La sortie de l'exécution du programme ci-dessus est la suivante:

面积为: 72.0
面积为: 432.0

Interne et externe nom du paramètre

Fonctions et méthodes avec les mêmes paramètres, paramètres structurels, il y a aussi le nom d'un paramètre dans le constructeur pour un usage interne et les noms de paramètres externes utilisés lors de l'appel d'un constructeur.

Cependant, la configuration est pas avant qu'il y ait un nom reconnaissable entre parenthèses comme fonctions et méthodes. Alors, appelez le constructeur, le constructeur est déterminé principalement par la nécessité d'appeler les noms des paramètres constructeur et types.

Si vous ne fournissez pas d'arguments lorsque vous définissez le nom externe du constructeur, Swift va générer automatiquement un nom avec le même nom interne externe pour chaque paramètre du constructeur.

struct Color {
    let red, green, blue: Double
    init(red: Double, green: Double, blue: Double) {
        self.red   = red
        self.green = green
        self.blue  = blue
    }
    init(white: Double) {
        red   = white
        green = white
        blue  = white
    }
}

// 创建一个新的Color实例,通过三种颜色的外部参数名来传值,并调用构造器
let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)

print("red 值为: \(magenta.red)")
print("green 值为: \(magenta.green)")
print("blue 值为: \(magenta.blue)")

// 创建一个新的Color实例,通过三种颜色的外部参数名来传值,并调用构造器
let halfGray = Color(white: 0.5)
print("red 值为: \(halfGray.red)")
print("green 值为: \(halfGray.green)")
print("blue 值为: \(halfGray.blue)")

La sortie de l'exécution du programme ci-dessus est la suivante:

red 值为: 1.0
green 值为: 0.0
blue 值为: 1.0
red 值为: 0.5
green 值为: 0.5
blue 值为: 0.5

Aucun nom de paramètre externe

Si vous ne voulez pas de fournir le nom externe pour un paramètre du constructeur, vous pouvez utiliser un trait de soulignement _ pour décrire son nom d'affichage externe.

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("面积为: \(rectarea.length)")

// 调用不提供外部名字
let rearea = Rectangle(370.0)
print("面积为: \(rearea.length)")

// 调用不提供外部名字
let recarea = Rectangle(110.0)
print("面积为: \(recarea.length)")

La sortie de l'exécution du programme ci-dessus est la suivante:

面积为: 180.0
面积为: 370.0
面积为: 110.0

Attributs facultatifs type

Si votre type personnalisé contient un argument logique pour permettre vides attributs de type de stockage, vous devez définir comme une option de type de type en option (option de type d'attribut).

Lors du stockage de déclaration de propriété est facultative, il sera automatiquement initialisé à vide nul.

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("面积为:\(rectarea.length)")

let rearea = Rectangle(370.0)
print("面积为:\(rearea.length)")

let recarea = Rectangle(110.0)
print("面积为:\(recarea.length)")

La sortie de l'exécution du programme ci-dessus est la suivante:

面积为:Optional(180.0)
面积为:Optional(370.0)
面积为:Optional(110.0)

Modifier la propriété Constant processus de construction

Juste avant la fin du processus de construction peut déterminer la valeur d'une constante, vous pouvez modifier la valeur des attributs constants à tout moment dans le processus de construction.

Pour une instance de classe, son attribut constant ne peut être défini dans ses classes modifications de processus de construction, ne peut pas être changé dans une sous-classe.

En dépit de la propriété length est maintenant est une constante, nous pouvons encore définir sa valeur dans le constructeur de sa classe:

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("面积为:\(rectarea.length)")

let rearea = Rectangle(370.0)
print("面积为:\(rearea.length)")

let recarea = Rectangle(110.0)
print("面积为:\(recarea.length)")

La sortie de l'exécution du programme ci-dessus est la suivante:

面积为:Optional(180.0)
面积为:Optional(370.0)
面积为:Optional(110.0)

Le constructeur par défaut

Le constructeur par défaut va simplement créer toutes les valeurs de propriété sont mis à l'instance par défaut:

Les exemples suivants, la classe de toutes les propriétés a une valeur par défaut, et il est pas le père de la classe de base, il sera automatiquement obtenir un peut définir des valeurs par défaut pour toutes les propriétés du constructeur par défaut

class ShoppingListItem {
    var name: String?
    var quantity = 1
    var purchased = false
}
var item = ShoppingListItem()


print("名字为: \(item.name)")
print("数理为: \(item.quantity)")
print("是否付款: \(item.purchased)")

La sortie de l'exécution du programme ci-dessus est la suivante:

名字为: nil
数理为: 1
是否付款: false

Chaque élément de la structure du constructeur

Si la structure de toutes les propriétés de stockage de type fournissent des valeurs par défaut et ne fournissent pas leur propre constructeur personnalisé, ils obtiennent automatiquement chaque membre d'un constructeur.

Lorsque nous appelons à chaque membre du constructeur, en effectuant les valeurs traditionnelles et les membres du même nom attribut nom du paramètre pour compléter l'attribution initiale des propriétés des membres.

L'exemple suivant définit une structure Rectangle, qui contient deux attributs longueur et la largeur. Swift peut être attribué en fonction de la première 100,0 de ces deux propriétés, 200,0 dérivent automatiquement leur type Double.

struct Rectangle {
    var length = 100.0, breadth = 200.0
}
let area = Rectangle(length: 24.0, breadth: 32.0)

print("矩形的面积: \(area.length)")
print("矩形的面积: \(area.breadth)")

Étant donné que les propriétés de deux stockage ont des valeurs par défaut, les structures Rectangle automatiquement un membre de chaque constructeur init (largeur: hauteur :). Vous pouvez l'utiliser pour créer une nouvelle instance de Rectangle.

La sortie de l'exécution du programme ci-dessus est la suivante:

名字为: nil
矩形的面积: 24.0
矩形的面积: 32.0

Valeur Agent type de constructeur

Constructor en appelant d'autres constructeurs pour compléter une partie de l'instance de processus de construction. Ce processus est appelé agent de structure, il peut réduire la duplication de code entre plusieurs constructeurs.

Les exemples suivants, Rect processus de construction de structure appelée et point Taille de:

struct Size {
    var width = 0.0, height = 0.0
}
struct Point {
    var x = 0.0, y = 0.0
}

struct Rect {
    var origin = Point()
    var size = Size()
    init() {}
    init(origin: Point, size: Size) {
        self.origin = origin
        self.size = size
    }
    init(center: Point, size: Size) {
        let originX = center.x - (size.width / 2)
        let originY = center.y - (size.height / 2)
        self.init(origin: Point(x: originX, y: originY), size: size)
    }
}


// origin和size属性都使用定义时的默认值Point(x: 0.0, y: 0.0)和Size(width: 0.0, height: 0.0):
let basicRect = Rect()
print("Size 结构体初始值: \(basicRect.size.width, basicRect.size.height) ")
print("Rect 结构体初始值: \(basicRect.origin.x, basicRect.origin.y) ")

// 将origin和size的参数值赋给对应的存储型属性
let originRect = Rect(origin: Point(x: 2.0, y: 2.0),
    size: Size(width: 5.0, height: 5.0))

print("Size 结构体初始值: \(originRect.size.width, originRect.size.height) ")
print("Rect 结构体初始值: \(originRect.origin.x, originRect.origin.y) ")


//先通过center和size的值计算出origin的坐标。
//然后再调用(或代理给)init(origin:size:)构造器来将新的origin和size值赋值到对应的属性中
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
    size: Size(width: 3.0, height: 3.0))

print("Size 结构体初始值: \(centerRect.size.width, centerRect.size.height) ")
print("Rect 结构体初始值: \(centerRect.origin.x, centerRect.origin.y) ")

La sortie de l'exécution du programme ci-dessus est la suivante:

Size 结构体初始值: (0.0, 0.0) 
Rect 结构体初始值: (0.0, 0.0) 
Size 结构体初始值: (5.0, 5.0) 
Rect 结构体初始值: (2.0, 2.0) 
Size 结构体初始值: (3.0, 3.0) 
Rect 结构体初始值: (2.5, 2.5) 

règles Constructor proxy

type de valeur Type de classe
Il ne supporte pas l'héritage, de sorte que le processus est agent de structure relativement simple, comme d'autres agents, ils ne peuvent constructeur de se donner. Vous pouvez utiliser référence self.init autre constructeur appartenant au même type de valeur dans un constructeur personnalisé. Il peut hériter d'autres classes, ce qui signifie que la classe a la responsabilité d'assurer l'ensemble de ses propriétés héritées lorsque la structure de type de stockage peut être correctement initialisé.

processus de la classe Héritage et construction

Swift fournit deux types de constructeur de classe pour veiller à ce que toutes les instances des propriétés de classe de stockage peuvent être obtenues dans les valeurs initiales, qui sont spécifiées constructeur et constructeur de commodité.

Indique le constructeur constructeur Commodité
Le constructeur de la classe principale Classe relativement mineure, constructeur assistée
Tous les biens sont de classe initialisée offert et appeler le constructeur de la classe mère basée sur la chaîne parent pour obtenir l'initialisation de la classe parente. Vous pouvez définir constructeur de commodité pour appeler la même classe que spécifiée dans le constructeur, et fournit des valeurs par défaut pour les paramètres. Vous pouvez également définir constructeur de commodité pour créer une instance d'un usage particulier ou d'intrants spécifiques.
Chaque classe doit avoir au moins un constructeur spécifié Seulement lorsque cela est nécessaire pour faciliter le constructeur de classe
Init(parameters) {
    statements
}
convenience init(parameters) {
      statements
}

Indique le constructeur d'instance

class mainClass {
    var no1 : Int // 局部存储变量
    init(no1 : Int) {
        self.no1 = no1 // 初始化
    }
}
class subClass : mainClass {
    var no2 : Int // 新的子类存储变量
    init(no1 : Int, no2 : Int) {
        self.no2 = no2 // 初始化
        super.init(no1:no1) // 初始化超类
    }
}

let res = mainClass(no1: 10)
let res2 = subClass(no1: 10, no2: 20)

print("res 为: \(res.no1)")
print("res2 为: \(res2.no1)")
print("res2 为: \(res2.no2)")

La sortie de l'exécution du programme ci-dessus est la suivante:

res 为: 10
res 为: 10
res 为: 20

Des exemples de constructeur de commodité

class mainClass {
    var no1 : Int // 局部存储变量
    init(no1 : Int) {
        self.no1 = no1 // 初始化
    }
}

class subClass : mainClass {
    var no2 : Int
    init(no1 : Int, no2 : Int) {
        self.no2 = no2
        super.init(no1:no1)
    }
    // 便利方法只需要一个参数
    override convenience init(no1: Int)  {
        self.init(no1:no1, no2:0)
    }
}
let res = mainClass(no1: 20)
let res2 = subClass(no1: 30, no2: 50)

print("res 为: \(res.no1)")
print("res2 为: \(res2.no1)")
print("res2 为: \(res2.no2)")

La sortie de l'exécution du programme ci-dessus est la suivante:

res 为: 20
res2 为: 30
res2 为: 50

Héritage et constructeur surcharge

sous-classe Swift ne hérite pas le constructeur par défaut de la classe parent.

Le constructeur de la classe parent est hérité seulement dans la détermination de cas et de la sécurité.

Lorsque vous remplacez un constructeur de classe parent spécifié, vous devez écrire un modificateur override.

class SuperClass {
    var corners = 4
    var description: String {
        return "\(corners) 边"
    }
}
let rectangle = SuperClass()
print("矩形: \(rectangle.description)")

class SubClass: SuperClass {
    override init() {  //重载构造器
        super.init()
        corners = 5
    }
}

let subClass = SubClass()
print("五角型: \(subClass.description)")

La sortie de l'exécution du programme ci-dessus est la suivante:

矩形: 4 边
五角型: 5 边

Indique les exemples constructeur et de commodité constructeurs

L'exemple suivant fera la démonstration de l'opération spécifiée dans le constructeur, les constructeurs et faciliter l'héritage constructeur automatique.

Il contient deux classes MainClass, la hiérarchie des classes de SubClass définies, et démontrer comment leur interaction avec les constructeurs.

class MainClass {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    convenience init() {
        self.init(name: "[匿名]")
    }
}
let main = MainClass(name: "w3big")
print("MainClass 名字为: \(main.name)")

let main2 = MainClass()
print("没有对应名字: \(main2.name)")

class SubClass: MainClass {
    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)
    }
}

let sub = SubClass(name: "w3big")
print("MainClass 名字为: \(sub.name)")

let sub2 = SubClass(name: "w3big", count: 3)
print("count 变量: \(sub2.count)")

La sortie de l'exécution du programme ci-dessus est la suivante:

MainClass 名字为: w3big
没有对应名字: [匿名]
MainClass 名字为: w3big
count 变量: 3

Le constructeur de classe peut échouer

Si un objet, une structure ou type d'énumération de classe, il est possible de se structurer dans le processus échoue, l'échec de définir un constructeur.

initialisation Variable Les raisons possibles ont échoué sont:

  • Incoming valeur de paramètre non valide.

  • Manquant certaines ressources externes nécessaires.

  • Il ne répondait pas à certaines conditions.

Afin de traiter correctement le cas de ce processus de configuration peut échouer.

Vous pouvez dans une définition de la structure de type classe ou enum, ajouter un ou constructeur plus échoué. La syntaxe est un point d'interrogation init mot-clé Jiatian (init?).

Exemples

Dans l'exemple suivant, la définition d'une structure appelée un animal, qui a nommé l'espèce, le type String attribut constantes.

Pendant ce temps, la structure définit également une avec une espèce de paramètre de type String peut échouer constructeur. Le constructeur peut échouer, est utilisé pour vérifier si l'argument passé à une chaîne vide, une chaîne vide, le constructeur peut échouer, l'échec de construire un objet, sinon le succès.

struct Animal {
    let species: String
    init?(species: String) {
        if species.isEmpty { return nil }
        self.species = species
    }
}

//通过该可失败构造器来构建一个Animal的对象,并检查其构建过程是否成功
// someCreature 的类型是 Animal? 而不是 Animal
let someCreature = Animal(species: "长颈鹿")

// 打印 "动物初始化为长颈鹿"
if let giraffe = someCreature {
    print("动物初始化为\(giraffe.species)")
}

La sortie de l'exécution du programme ci-dessus est la suivante:

动物初始化为长颈鹿

constructeur de type Enumération peut échouer

Vous pouvez avec un ou plusieurs paramètres peuvent être configurés par le constructeur échoué à obtenir un membres de l'énumération spécifiques de type énuméré.

Exemples

Dans l'exemple suivant, la définition d'un type énuméré nommé TemperatureUnit. Qui contient trois possibles membre enum (Kelvin, Celsius et Fahrenheit) et un échec peut être utilisé pour trouver les valeurs constructeur de caractères membres de l'énumération correspondant:

enum TemperatureUnit {
	// 开尔文,摄氏,华氏
    case Kelvin, Celsius, Fahrenheit
    init?(symbol: Character) {
        switch symbol {
        case "K":
            self = .Kelvin
        case "C":
            self = .Celsius
        case "F":
            self = .Fahrenheit
        default:
            return nil
        }
    }
}


let fahrenheitUnit = TemperatureUnit(symbol: "F")
if fahrenheitUnit != nil {
    print("这是一个已定义的温度单位,所以初始化成功。")
}

let unknownUnit = TemperatureUnit(symbol: "X")
if unknownUnit == nil {
    print("这不是一个已定义的温度单位,所以初始化失败。")
}

La sortie de l'exécution du programme ci-dessus est la suivante:

这是一个已定义的温度单位,所以初始化成功。
这不是一个已定义的温度单位,所以初始化失败。

Le constructeur de classe peut échouer

Les types de valeur (tels que les structures ou type énuméré) peuvent échouer constructeur, quand et où pour déclencher la construction échoue sans aucune limitation de ce comportement.

Cependant, le constructeur de classe peut échouer et l'agent ne peut appeler le constructeur parmi toutes les classes a eu lieu dans toutes les propriétés de classe sont initialisés après le comportement de panne d'allumage.

Exemples

Par exemple, la définition d'une classe appelée StudRecord parce que la propriété studname est une constante, donc une fois que le succès de constructeur de classe StudRecord, propriété studname doit avoir une valeur non nulle.

class StudRecord {
    let studname: String!
    init?(studname: String) {
        self.studname = studname
        if studname.isEmpty { return nil }
    }
}
if let stname = StudRecord(studname: "失败构造器") {
    print("模块为 \(stname.studname)")
}

La sortie de l'exécution du programme ci-dessus est la suivante:

模块为 失败构造器

Couvrant un constructeur peut échouer

Comme d'autres constructeurs, comme, vous pouvez également remplacer le constructeur de classe de base peut échouer avec la sous-classe constructeur peut échouer.

Vous pouvez également remplacer par un constructeur de classe de base peut échouer avec l'échec de la non-constructeur sous-classe.

Vous pouvez utiliser un constructeur non échoué couvrant un constructeur peut échouer, mais à son tour, il ne fonctionne pas.

Un constructeur non échoué ne peut jamais appeler un agent peut échouer constructeur.

Exemples

L'exemple suivant décrit un échec et non-échec Constructor:

class Planet {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    convenience init() {
        self.init(name: "[No Planets]")
    }
}
let plName = Planet(name: "Mercury")
print("行星的名字是: \(plName.name)")

let noplName = Planet()
print("没有这个名字的行星: \(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)
    }
}

La sortie de l'exécution du programme ci-dessus est la suivante:

行星的名字是: Mercury
没有这个名字的行星: [No Planets]

Peut échouer constructeur initialisation!

En règle générale, nous ajoutons un point d'interrogation après la façon dont mot-clé init (init?) Peut ne pas définir un constructeur, mais vous pouvez également utiliser init en ajoutant un point d'exclamation après la façon de définir un constructeur échoué (init!) . Des exemples sont les suivants:

struct StudRecord {
    let stname: String
    
    init!(stname: String) {
        if stname.isEmpty {return nil }
        self.stname = stname
    }
}

let stmark = StudRecord(stname: "w3big")
if let name = stmark {
    print("指定了学生名")
}

let blankname = StudRecord(stname: "")
if blankname == nil {
    print("学生名为空")
}

La sortie de l'exécution du programme ci-dessus est la suivante:

指定了学生名
学生名为空