Latest web development tutorials

processo de construção Swift

processo de construção é usar uma instância de uma classe, estrutura ou tipo de enumeração realizado o processo de preparação. Este processo envolve a definição de valores iniciais para cada atributo ea instância para a preparação e implementação das tarefas de inicialização necessários.

Swift construtor método init ().

E Objective-C no construtor diferente, o construtor Swift não precisa retornar um valor, a sua principal tarefa é assegurar que a nova instância é concluída antes da primeira utilização inicialização adequada.

instâncias de classe pode ser definida destructor (deinitializer) Memória trabalho de limpeza antes de instância de classe é liberado.


A atribuição inicial da propriedade de tipo de armazenamento

Classes e estruturas quando uma instância é criada, ela deve definir o valor inicial adequada para todos os atributos do tipo de armazenamento.

Ao armazenar atribuição de propriedade no construtor, os seus valores são definidos diretamente e não desencadear qualquer observador propriedade.

processo de atribuição de propriedade de armazenamento no construtor:

  • Criando o valor inicial.

  • Na definição de atributo especifica os valores de propriedade padrão.

  • Inicializa uma instância, e chama o método init ().


construtor

O construtor é chamado quando você cria uma nova instância de um tipo particular. Sua forma mais simples é semelhante a um método de instância sem quaisquer parâmetros, o nome de init palavra-chave.

gramática

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

Exemplos

A estrutura a seguir define init um construtor sem argumentos, e no interior do comprimento atributo do tipo de armazenamento e largura do valor de inicialização de 6 e 12:

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

A saída de execução de programa acima é:

矩形面积为 72.0

valores de propriedade padrão

Podemos definir os valores iniciais para a propriedade do tipo de armazenamento no construtor; Além disso, é possível definir um valor padrão quando uma declaração de propriedade.

Ele permite que você use o aspirador construtor padrão, mais claro, e pode automaticamente inferir pelo atributo tipo de valor predefinido.

O exemplo a seguir queremos definir o valor padrão quando uma declaração de propriedade:

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

A saída de execução de programa acima é:

矩形面积为 72

parâmetros de configuração

Você pode definir o construtor desde que o parâmetro de construtor init (), como segue:

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)")

A saída de execução de programa acima é:

面积为: 72.0
面积为: 432.0

nome do parâmetro interno e externo

Funções e métodos com os mesmos parâmetros, parâmetros estruturais há também o nome de um parâmetro no construtor para uso interno e nomes de parâmetros externos usados ​​ao chamar um construtor.

No entanto, a configuração não é, como antes, há um nome reconhecível nos suportes como funções e métodos. Então chamar o construtor, o construtor é determinada principalmente pela necessidade de chamar os nomes de parâmetros construtor e tipos.

Se você não fornecer argumentos quando você define o nome externo construtor, Swift irá gerar automaticamente um nome com o mesmo nome interno externa para cada parâmetro de construtor.

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)")

A saída de execução de programa acima é:

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

Nenhum nome de parâmetro externo

Se você não deseja fornecer nome externo para um parâmetro de construtor, você pode usar um sublinhado _ para descrever seu nome de exibição externo.

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)")

A saída de execução de programa acima é:

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

Atributos opcionais Tipo

Se o seu tipo personalizado contém um argumento lógico para permitir atributos do tipo de armazenamento vazias, você precisa defini-lo como um tipo opcional de tipo opcional (tipo de atributo opcional).

Ao armazenar declaração de propriedade é opcional, ele será inicializado automaticamente a zero vazio.

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)")

A saída de execução de programa acima é:

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

Modificar processo de construção constante Property

Pouco antes do fim do processo de construção pode determinar o valor de uma constante, é possível alterar o valor dos atributos constante em qualquer ponto no processo de construção.

Para uma instância de classe, seu atributo constante só pode ser definido em sua classe modificações processo de construção; não pode ser alterado em uma subclasse.

Apesar de a propriedade comprimento é agora é uma constante, ainda podemos definir o seu valor no construtor da sua 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)")

A saída de execução de programa acima é:

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

O construtor padrão

O construtor padrão simplesmente criar todos os valores de propriedades estão definidas para a instância padrão:

Os exemplos a seguir, todas as propriedades ShoppingListItem classe tem um valor padrão, e não é o pai da classe base, ele será automaticamente obter um pode definir valores padrão para todas as propriedades do construtor padrão

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


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

A saída de execução de programa acima é:

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

Cada membro da estrutura construtor

Se a estrutura de todas as propriedades do tipo de armazenamento fornecer valores padrão e não fornecer seu próprio construtor de costume, eles ficam automaticamente cada membro de um construtor.

Quando chamamos a cada membro do construtor, através da realização de valores tradicionais e os membros do mesmo nome do parâmetro nome do atributo para completar a atribuição inicial de propriedades do membro.

O exemplo a seguir define uma estrutura retangular, que contém comprimento dois atributos e amplitude. Swift pode ser atribuído de acordo com a inicial 100,0 destas duas propriedades, 200,0 derivar automaticamente o seu tipo duplo.

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

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

Uma vez que as propriedades de dois armazenamento têm valores padrão, estruturas retângulo automaticamente um membro de cada inicialização do construtor (largura: altura :). Você pode usá-lo para criar uma nova instância do retângulo.

A saída de execução de programa acima é:

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

Valor Agente tipo construtor

Construtor chamando outros construtores para completar parte da instância do processo de construção. Este processo é chamado de agente de estrutura, ele pode reduzir a duplicação de código entre vários construtores.

Os exemplos a seguir, estrutura chamada Rect processo de construção e em tamanho de ponto 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) ")

A saída de execução de programa acima é:

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) 

regras de proxy construtor

Tipo de valor Tipo de classe
Ele não suporta herança, de modo que o processo é agente de estrutura relativamente simples, como outros agentes só podem construtor para dotar-se. Você pode usar de referência self.init outro construtor pertencentes ao mesmo tipo de valor em um construtor personalizado. Ele pode herdar de outras classes, o que significa que a classe tem a responsabilidade de assegurar todas as suas propriedades herdadas quando a estrutura do tipo de armazenamento pode ser inicializado corretamente.

processo de herança e construção da classe

Swift fornece dois tipos de construtor de classe para assegurar que todas as instâncias de classe-as propriedades de armazenamento podem ser obtidas nos valores iniciais, que são especificados construtor e construtor de conveniência.

Especifica o construtor construtor conveniência
O construtor da classe principal Classe relativamente menor, construtor assistida
Toda a propriedade é inicializada classe ofereceu-se e chamar o construtor da classe pai com base na cadeia de pais para conseguir a inicialização da classe pai. Você pode definir construtor conveniência de chamar a mesma classe, conforme especificado no construtor, e fornece valores padrão para parâmetros. Você também pode definir construtor conveniência para criar uma instância de um propósito particular ou insumos específicos.
Cada classe deve ter pelo menos um construtor especificado Somente quando necessário para facilitar o construtor da classe
Init(parameters) {
    statements
}
convenience init(parameters) {
      statements
}

Especifica o construtor de instância

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)")

A saída de execução de programa acima é:

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

Exemplos de construtor de conveniência

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)")

A saída de execução de programa acima é:

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

Herança e construtor sobrecarga

Swift sub-classe não herda o construtor padrão da classe pai.

O construtor da classe pai é herdado apenas na determinação caso e segurança.

Quando você substituir um construtor de classe pai especificada, você precisa escrever um modificador 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)")

A saída de execução de programa acima é:

矩形: 4 边
五角型: 5 边

Especifica os exemplos do construtor e de conveniência construtores

O exemplo a seguir irá demonstrar o funcionamento especificado no construtor, construtores e facilitar a herança construtor automático.

Ele contém duas classes MainClass, hierarquia de classes SubClass definidos, e demonstrar como a sua interacção construtores.

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)")

A saída de execução de programa acima é:

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

O construtor da classe pode falhar

Se uma classe, objeto, estrutura ou tipo de enumeração, é possível estruturar-se no processo falhar, a falha para definir um construtor.

inicialização de variáveis ​​falharam razões possíveis são:

  • Incoming valor de parâmetro inválido.

  • Faltando alguns recursos externos necessários.

  • Ele não cumprir determinadas condições.

A fim de lidar correctamente com o caso do presente processo de configuração pode falhar.

Você pode em uma definição de tipo de classe ou enum da estrutura, adicione um ou construtor mais falhou. A sintaxe é um ponto de interrogação após a inicialização chave Jiatian (init?).

Exemplos

No exemplo a seguir, a definição de uma estrutura denominada de animal, o que tem chamado a espécie, tipo String atributo constantes.

Enquanto isso, a estrutura também define um com uma espécie de parâmetro tipo String pode falhar construtor. O construtor pode falhar, é utilizado para verificar se o argumento passado para uma cadeia vazia, uma cadeia vazia, o construtor pode falhar, a incapacidade de construir um objeto, caso contrário, o sucesso.

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)")
}

A saída de execução de programa acima é:

动物初始化为长颈鹿

Enumerados construtor de tipo pode falhar

Você pode com um ou mais parâmetros podem ser configurados pelo construtor não conseguiu obter um tipo enumerado membros de enumeração específicos.

Exemplos

No exemplo a seguir, a definição de um tipo enumerado chamado TemperatureUnit. Que contém três possíveis membro enum (Kelvin, Celsius e Fahrenheit) e uma falha pode ser usada para encontrar os valores construtor de caracteres membros de enumeração correspondentes:

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("这不是一个已定义的温度单位,所以初始化失败。")
}

A saída de execução de programa acima é:

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

O construtor da classe pode falhar

Tipos de valor (como estruturas ou tipo enumerado) pode falhar construtor, quando e onde para acionar a construção falhar sem qualquer limitação deste comportamento.

No entanto, o construtor da classe pode falhar e o agente só pode chamar o construtor entre todas as classes ocorreu em todas as propriedades da classe são inicializados depois comportamento falha de ignição.

Exemplos

Por exemplo, a definição de uma classe chamada StudRecord porque a propriedade studname é uma constante, assim que uma vez o sucesso construtor da classe StudRecord, propriedade studname deve ter um valor diferente de zero.

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

A saída de execução de programa acima é:

模块为 失败构造器

Cobrindo um construtor pode falhar

À semelhança de outros construtores, como, você também pode substituir o construtor classe base pode falhar com o construtor da subclasse pode falhar.

Você também pode substituir por um construtor da classe base pode falhar com o fracasso da subclasse não-construtor.

Você pode usar um construtor que não falhou cobrindo um construtor pode falhar, mas por sua vez, ele não funciona.

Um construtor que não falhou nunca pode chamar um agente pode falhar construtor.

Exemplos

O exemplo seguinte descreve uma falha e não falha Construtor:

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)
    }
}

A saída de execução de programa acima é:

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

Pode falhar construtor de inicialização!

Geralmente, nós adicionamos um ponto de interrogação depois da maneira como palavra-chave de inicialização (init?) Pode falhar ao definir um construtor, mas você também pode usar a inicialização, adicionando um ponto de exclamação após a maneira de definir um construtor falhou (init!) . Exemplos são os seguintes:

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("学生名为空")
}

A saída de execução de programa acima é:

指定了学生名
学生名为空