Latest web development tutorials

proses konstruksi Swift

proses konstruksi adalah dengan menggunakan sebuah instance dari kelas, struktur, atau jenis pencacahan dilakukan proses persiapan. Proses ini melibatkan pengaturan nilai awal untuk masing-masing atribut dan contoh untuk penyusunan dan pelaksanaan tugas inisialisasi yang diperlukan.

Swift konstruktor init () metode.

Dan Objective-C di konstruktor yang berbeda, constructor Swift tidak perlu mengembalikan nilai, tugas utama mereka adalah untuk memastikan bahwa contoh baru selesai sebelum inisialisasi yang tepat penggunaan pertama.

contoh kelas dapat didefinisikan destructor (deinitializer) memori kerja pembersihan sebelum instance kelas dilepaskan.


Awal penugasan properti penyimpanan-jenis

Kelas dan struktur ketika sebuah instance dibuat, harus mengatur nilai awal yang tepat untuk semua atribut penyimpanan tipe.

Ketika menyimpan tugas properti di konstruktor, nilai-nilai mereka diatur langsung dan tidak memicu pengamat properti.

proses tugas properti penyimpanan dalam constructor:

  • Menciptakan nilai awal.

  • Dalam definisi atribut menentukan default nilai properti.

  • Menginisialisasi sebuah contoh, dan panggilan metode init ().


pembina

konstruktor dipanggil ketika Anda membuat contoh baru dari jenis tertentu. bentuk yang paling sederhana adalah mirip dengan metode contoh tanpa parameter apapun, kata kunci nama init.

tatabahasa

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

contoh

Struktur berikut mendefinisikan init konstruktor tanpa argumen, dan dalam jenis penyimpanan panjang atribut dan luasnya nilai inisialisasi 6 dan 12:

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

Output di atas eksekusi program adalah:

矩形面积为 72.0

nilai properti default

Kita dapat mengatur nilai awal untuk penyimpanan-jenis properti di konstruktor, Juga, dapat mengatur nilai default ketika deklarasi properti.

Hal ini memungkinkan Anda untuk menggunakan default constructor bersih, jelas, dan secara otomatis dapat disimpulkan dengan nilai default jenis atribut.

Contoh berikut kita ingin mengatur nilai default ketika deklarasi properti:

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

Output di atas eksekusi program adalah:

矩形面积为 72

parameter konfigurasi

Anda dapat menentukan konstruktor disediakan init () parameter konstruktor, sebagai berikut:

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

Output di atas eksekusi program adalah:

面积为: 72.0
面积为: 432.0

Internal dan eksternal nama parameter

Fungsi dan metode dengan parameter yang sama, parameter struktural ada juga nama parameter dalam konstruktor untuk penggunaan internal dan nama parameter eksternal digunakan saat memanggil konstruktor.

Namun, konfigurasi tidak seperti sebelumnya ada nama dikenali dalam kurung seperti fungsi dan metode. Jadi memanggil konstruktor, constructor ditentukan terutama oleh kebutuhan untuk memanggil nama-nama parameter konstruktor dan jenis.

Jika Anda tidak memberikan argumen ketika Anda mendefinisikan konstruktor nama eksternal, Swift otomatis akan menghasilkan nama dengan nama yang sama internal dan eksternal untuk setiap parameter konstruktor.

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

Output di atas eksekusi program adalah:

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

Tidak ada nama parameter eksternal

Jika Anda tidak ingin memberikan nama eksternal untuk parameter konstruktor, Anda dapat menggunakan garis bawah _ untuk menggambarkan nama tampilan eksternal.

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

Output di atas eksekusi program adalah:

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

Atribut opsional Type

Jika jenis kustom Anda berisi argumen logis untuk memungkinkan atribut penyimpanan tipe kosong, Anda perlu mendefinisikannya sebagai jenis opsional opsional Jenis (opsional jenis atribut).

Ketika menyimpan deklarasi properti adalah opsional, maka akan secara otomatis diinisialisasi nihil kosong.

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

Output di atas eksekusi program adalah:

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

Memodifikasi proses konstruksi Properti Constant

Sebelum akhir dari proses konstruksi dapat menentukan nilai sebuah konstanta, Anda dapat mengubah nilai atribut konstan pada setiap titik dalam proses konstruksi.

Untuk contoh kelas, atribut konstan hanya dapat didefinisikan dalam modifikasi proses konstruksi kelasnya, tidak dapat diubah dalam subclass.

Meskipun properti panjang sekarang adalah konstan, kita masih bisa mengatur nilai dalam konstruktor dari kelasnya:

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

Output di atas eksekusi program adalah:

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

Default constructor

Konstruktor default hanya akan membuat semua nilai properti ditetapkan untuk contoh default:

Contoh-contoh berikut, semua properti ShoppingListItem kelas memiliki nilai default, dan itu bukan ayah dari kelas dasar, maka secara otomatis akan mendapatkan dapat mengatur nilai default untuk semua properti dari konstruktor default

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


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

Output di atas eksekusi program adalah:

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

Setiap anggota dari struktur konstruktor

Jika struktur dari semua sifat penyimpanan tipe menyediakan nilai default dan tidak memberikan builder adat mereka sendiri, mereka secara otomatis mendapatkan setiap anggota konstruktor.

Ketika kita sebut untuk setiap anggota konstruktor, dengan melakukan nilai-nilai tradisional dan anggota nama atribut nama parameter yang sama untuk menyelesaikan tugas awal dari sifat anggota.

Contoh berikut mendefinisikan struktur Rectangle, yang berisi dua atribut panjang dan lebarnya. Swift dapat ditugaskan sesuai dengan awal 100,0 dari dua sifat tersebut, 200,0 otomatis berasal jenis mereka ganda.

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

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

Karena sifat dua storage memiliki nilai default, struktur Rectangle otomatis anggota dari masing-masing init konstruktor (lebar: tinggi :). Anda dapat menggunakannya untuk membuat contoh baru dari Rectangle.

Output di atas eksekusi program adalah:

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

Nilai Agen tipe konstruktor

Konstruktor dengan memanggil konstruktor lain untuk menyelesaikan bagian dari contoh proses konstruksi. Proses ini disebut agen struktur, dapat mengurangi duplikasi kode antara beberapa konstruktor.

Contoh-contoh berikut, Rect struktur disebut proses konstruksi dan Titik Ukuran:

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

Output di atas eksekusi program adalah:

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) 

aturan konstruktor Proxy

nilai Type Jenis kelas
Tidak mendukung warisan, sehingga proses ini agen struktur yang relatif sederhana, sebagai agen lain mereka hanya konstruktor untuk menyediakan sendiri. Anda dapat menggunakan referensi self.init konstruktor lain milik jenis yang sama dari nilai dalam konstruktor kustom. Hal ini dapat mewarisi dari kelas-kelas lain, yang berarti bahwa kelas memiliki tanggung jawab untuk memastikan semua sifat-sifatnya diturunkan ketika struktur penyimpanan-jenis dapat diinisialisasi dengan benar.

Warisan dan konstruksi proses kelas

Swift menyediakan dua jenis kelas konstruktor untuk memastikan bahwa semua contoh dari properti kelas-storage dapat diperoleh di nilai awal, yang ditentukan konstruktor dan kenyamanan konstruktor.

Menentukan konstruktor kenyamanan konstruktor
Utama konstruktor kelas Kelas relatif kecil, konstruktor dibantu
Semua properti kelas diinisialisasi ditawarkan dan memanggil konstruktor dari kelas induk berdasarkan rantai induk untuk mencapai inisialisasi kelas induk. Anda dapat menentukan kenyamanan konstruktor untuk memanggil kelas yang sama seperti yang ditentukan dalam constructor, dan memberikan nilai default untuk parameter. Anda juga dapat menentukan kenyamanan konstruktor untuk membuat sebuah instance dari tujuan tertentu atau masukan tertentu.
Setiap kelas harus memiliki setidaknya konstruktor ditentukan Hanya bila diperlukan untuk memfasilitasi konstruktor kelas
Init(parameters) {
    statements
}
convenience init(parameters) {
      statements
}

Menentukan contoh konstruktor

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

Output di atas eksekusi program adalah:

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

Contoh kenyamanan konstruktor

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

Output di atas eksekusi program adalah:

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

Warisan dan konstruktor overloading

sub-kelas Swift tidak mewarisi konstruktor default dari kelas induk.

Konstruktor kelas induk diwariskan hanya dalam kasus penentuan dan keamanan.

Ketika Anda menimpa konstruktor kelas induk ditentukan, Anda perlu untuk menulis sebuah pengubah 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)")

Output di atas eksekusi program adalah:

矩形: 4 边
五角型: 5 边

Menentukan konstruktor dan kenyamanan konstruktor contoh

Contoh berikut akan menunjukkan operasi yang ditentukan dalam konstruktor, konstruktor dan memfasilitasi warisan konstruktor otomatis.

Ini berisi dua kelas didefinisikan MainClass, hirarki kelas subclass, dan menunjukkan bagaimana interaksi konstruktor mereka.

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

Output di atas eksekusi program adalah:

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

Kelas konstruktor bisa gagal

Jika kelas, objek, struktur, atau jenis pencacahan, adalah mungkin untuk struktur itu sendiri dalam proses gagal, kegagalan untuk mendefinisikan konstruktor.

Inisialisasi variabel gagal Alasan yang mungkin adalah:

  • Masuk nilai parameter tidak valid.

  • Hilang beberapa sumber eksternal yang diperlukan.

  • Tidak memenuhi kondisi tertentu.

Dalam rangka untuk benar menangani kasus proses konfigurasi ini mungkin gagal.

Anda dapat dalam jenis definisi kelas, atau enum struktur, tambahkan satu atau konstruktor lebih gagal. sintaks adalah tanda tanya setelah init kata kunci Jiatian (init?).

contoh

Pada contoh berikut, definisi struktur yang disebut Animal, yang telah menamai spesies, tipe String atribut konstanta.

Sementara itu, struktur juga mendefinisikan dengan spesies jenis parameter String bisa gagal konstruktor. Konstruktor bisa gagal, digunakan untuk memeriksa apakah argumen dilewatkan ke string kosong, string kosong, konstruktor bisa gagal, kegagalan untuk membangun sebuah objek, jika tidak sukses.

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

Output di atas eksekusi program adalah:

动物初始化为长颈鹿

Disebutkan tipe konstruktor bisa gagal

Anda bisa dengan satu atau lebih parameter dapat dikonfigurasi oleh constructor gagal mendapatkan tipe enumerasi anggota pencacahan tertentu.

contoh

Pada contoh berikut, definisi tipe enumerasi bernama TemperatureUnit. Yang berisi tiga kemungkinan anggota enum (Kelvin, Celsius, dan Fahrenheit) dan kegagalan dapat digunakan untuk menemukan nilai-nilai konstruktor Karakter yang sesuai anggota pencacahan:

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

Output di atas eksekusi program adalah:

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

Kelas konstruktor bisa gagal

jenis nilai (seperti struktur atau tipe enumerasi) mungkin gagal konstruktor, kapan dan di mana untuk memicu pembangunan gagal tanpa batasan perilaku ini.

Namun, konstruktor kelas bisa gagal dan agen hanya dapat memanggil konstruktor di antara semua kelas terjadi di semua properti kelas diinisialisasi setelah perilaku kegagalan pengapian.

contoh

Dengan contoh, definisi kelas yang disebut StudRecord karena properti studname adalah konstan, sehingga setelah keberhasilan kelas StudRecord konstruktor, properti studname harus memiliki nilai non-nihil.

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

Output di atas eksekusi program adalah:

模块为 失败构造器

Meliputi konstruktor bisa gagal

Seperti konstruktor lainnya, seperti, Anda dapat juga menimpa konstruktor kelas dasar dapat gagal dengan konstruktor subclass bisa gagal.

Anda juga dapat menimpa oleh konstruktor kelas dasar dapat gagal dengan kegagalan non-konstruktor subclass.

Anda dapat menggunakan konstruktor non-gagal meliputi konstruktor bisa gagal, tetapi pada gilirannya, tidak bekerja.

Sebuah konstruktor non-gagal tidak pernah dapat menghubungi agen mungkin gagal konstruktor.

contoh

Contoh berikut menggambarkan kegagalan dan non-kegagalan Pembuat:

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

Output di atas eksekusi program adalah:

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

Mungkin gagal konstruktor init!

Umumnya, kita menambahkan tanda tanya setelah cara kunci init (init?) Semoga gagal untuk mendefinisikan konstruktor, tetapi Anda juga dapat menggunakan init dengan menambahkan tanda seru setelah cara untuk mendefinisikan konstruktor gagal (init!) . Contohnya adalah sebagai berikut:

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

Output di atas eksekusi program adalah:

指定了学生名
学生名为空