スウィフト建設プロセス
構築プロセスは、クラスのインスタンスを使用することで、構造体、または列挙型は、準備処理を行います。 このプロセスは、必要な初期化タスクの準備と実施のための各属性とインスタンスの初期値を設定することを含みます。
スウィフトコンストラクタのinit()メソッド。
そして、Objective-Cは異なるコンストラクタで、コンストラクタはスウィフトが値を返す必要はありません、彼らの主なタスクは、新しいインスタンスが最初に使用する適切な初期化の前に完了したことを確認することです。
クラスのインスタンスが解放される前に、クラスのインスタンスは、デストラクタ(deinitializer)メモリのクリーンアップ作業を定義することができます。
蓄積型プロパティの初期割り当て
インスタンスの作成時にクラスと構造体は、それがすべてのストレージ型の属性に適切な初期値を設定する必要があります。
コンストラクタでプロパティの割り当てを保管するときは、その値が直接設定され、任意のプロパティオブザーバをトリガしません。
コンストラクタのストレージプロパティ割り当てプロセス:
初期値を作成します。
属性定義ではデフォルトのプロパティ値を指定します。
インスタンスを初期化し、init()メソッドを呼び出します。
コンストラクタ
あなたが特定の型の新しいインスタンスを作成するとき、コンストラクタが呼び出されます。 その最も単純な形態は、任意のパラメータを指定せずにインスタンスメソッド、キーワードのinit名前に似ています。
文法
init() { // 实例化后执行的代码 }
例
次の構造は、initを引数なしのコンストラクタを定義し、6と12の初期値のストレージタイプ属性の長さと幅の内側:
struct rectangle { var length: Double var breadth: Double init() { length = 6 breadth = 12 } } var area = rectangle() print("矩形面积为 \(area.length*area.breadth)")
上記プログラム実行出力は、次のとおりです。
矩形面积为 72.0
デフォルトのプロパティ値
私たちは、コンストラクタで蓄積型プロパティの初期値を設定することができます。また、デフォルト値プロパティ宣言を設定することができます。
それは明確に、あなたはデフォルトコンストラクタクリーナーを使用することができ、かつ自動的にデフォルト値type属性によって推測することができます。
次の例では、我々はデフォルト値を設定したいときに、プロパティの宣言:
struct rectangle { // 设置默认值 var length = 6 var breadth = 12 } var area = rectangle() print("矩形的面积为 \(area.length*area.breadth)")
上記プログラム実行出力は、次のとおりです。
矩形面积为 72
構成パラメータ
次のようにと、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("面积为: \(ar.area)") let are = Rectangle(fromLeng: 36, fromBread: 12) print("面积为: \(are.area)")
上記プログラム実行出力は、次のとおりです。
面积为: 72.0 面积为: 432.0
内部および外部パラメータ名
関数と同じパラメータを持つメソッドは、構造パラメータは、内部使用およびコンストラクタを呼び出すときに使用される外部パラメータ名のコンストラクタ内のパラメータの名前があります。
ただし、構成が認識可能な名前は関数やメソッドなどの括弧内に存在する以前のようではありません。 だから、コンストラクタを呼び出し、コンストラクタは、コンストラクタのパラメータの名前とタイプをコールする必要性によって主に決定されます。
あなたはコンストラクタ外部名を定義する引数を指定しない場合、スウィフトは自動的に各コンストラクタのパラメータに同じ外部内部名と名前を生成します。
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)")
上記プログラム実行出力は、次のとおりです。
red 值为: 1.0 green 值为: 0.0 blue 值为: 1.0 red 值为: 0.5 green 值为: 0.5 blue 值为: 0.5
外部パラメータ名ません
あなたはコンストラクタパラメータの外部名を提供したくない場合は、アンダースコアを使用することができます_
その外部の表示名を記述すること。
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)")
上記プログラム実行出力は、次のとおりです。
面积为: 180.0 面积为: 370.0 面积为: 110.0
オプション属性の種類
カスタム・タイプが空の蓄積型の属性を許可するように論理的な引数が含まれている場合は、オプションのタイプ、オプションタイプ(オプション属性の型)として定義する必要があります。
保存するプロパティの宣言はオプションである場合には、自動的に空のnilに初期化されます。
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)")
上記プログラム実行出力は、次のとおりです。
面积为:Optional(180.0) 面积为:Optional(370.0) 面积为:Optional(110.0)
定数プロパティ構築プロセスを変更します。
構築プロセスの終了は、定数の値を決定することができるだけ前に、構築プロセスの任意の時点で一定の属性の値を変更することができます。
クラスインスタンスの場合は、その一定の属性は、そのクラスの建設プロセスの変更で定義することができます;サブクラスで変更することはできません。
lengthプロパティが今一定であるにもかかわらず、我々はまだそのクラスのコンストラクタで、その値を設定することができます。
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)")
上記プログラム実行出力は、次のとおりです。
面积为:Optional(180.0) 面积为:Optional(370.0) 面积为:Optional(110.0)
デフォルトコンストラクタ
単にプロパティ値のすべてを作成するデフォルトコンストラクタが既定のインスタンスに設定されています。
以下の例は、すべてのプロパティShoppingListItemクラスはデフォルト値があり、そしてそれは、基本クラスの父ではない、それは自動的にデフォルトコンストラクタのすべてのプロパティのデフォルト値を設定することができます取得します
class ShoppingListItem { var name: String? var quantity = 1 var purchased = false } var item = ShoppingListItem() print("名字为: \(item.name)") print("数理为: \(item.quantity)") print("是否付款: \(item.purchased)")
上記プログラム実行出力は、次のとおりです。
名字为: nil 数理为: 1 是否付款: false
コンストラクタ構造体の各メンバ
すべてのストレージ型のプロパティの構造は、デフォルト値を提供し、独自のカスタムビルダーを提供しない場合は、自動的にコンストラクタの各メンバーを取得します。
私たちは、メンバプロパティの初期割り当てを完了するために、伝統的な価値観と同じ名前の属性パラメータ名のメンバーを実行することにより、コンストラクタの各メンバーに呼び出すと。
次の例では、2つの属性の長さと幅を含む構造矩形を定義します。 スウィフトは、これら2つのプロパティの初期100.0に応じて割り当てることができ、200.0は、自動的にそのタイプダブルを導き出します。
struct Rectangle { var length = 100.0, breadth = 200.0 } let area = Rectangle(length: 24.0, breadth: 32.0) print("矩形的面积: \(area.length)") print("矩形的面积: \(area.breadth)")
高:):2-保存性は、デフォルト値、構造自動的に長方形の各コンストラクタは、init(幅のメンバーを持っているので。 あなたは、Rectangleの新しいインスタンスを作成するためにそれを使用することができます。
上記プログラム実行出力は、次のとおりです。
名字为: nil 矩形的面积: 24.0 矩形的面积: 32.0
値型コンストラクタエージェント
建設プロセスインスタンスの一部を完了するために他のコンストラクタを呼び出すことで、コンストラクタ。 このプロセスは、構造化剤と呼ばれ、それは複数のコンストラクタとの間のコードの重複を減らすことができます。
以下の例で、RECT構造体と呼ばれる建設プロセスとポイントサイズの:
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) ")
上記プログラム実行出力は、次のとおりです。
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)
コンストラクタのプロキシルール
値タイプ | クラスタイプ |
---|---|
プロセスは比較的単純な構造剤であるので、彼らは唯一のコンストラクタは、それ自体を提供することができる他の薬剤としては、継承をサポートしていません。 カスタムコンストラクタで値の同じ型に属するself.init参照他のコンストラクタを使用することができます。 | これは、クラスが蓄積型構造が適切に初期化することができたときに、その継承されたプロパティのすべてを確実にする責任があることを意味し、他のクラスから継承することができます。 |
クラスの継承と建設プロセス
スウィフトは、クラスのストレージプロパティのすべてのインスタンスは、コンストラクタやコンビニエンスコンストラクタを指定された初期値、で得ることができることを確実にするために、クラスのコンストラクタの2種類が用意されています。
コンストラクタを指定します。 | コンビニエンスコンストラクタ |
メインクラスのコンストラクタ | クラスの比較的マイナー、補助コンストラクタ |
すべてのプロパティが初期化されたクラスささげと親クラスの初期化を達成するために、親チェーンに基づいて、親クラスのコンストラクタを呼び出しています。 | あなたは、コンストラクタに指定されたように同じクラスを呼び出すために便利なコンストラクタを定義し、パラメータのデフォルト値を提供することができます。 また、特定の目的や特定の入力のインスタンスを作成する簡易コンストラクタを定義することができます。 |
各クラスには、少なくとも指定されたコンストラクタを持っている必要があります | クラスのコンストラクタを容易にするために必要な場合にのみ |
Init(parameters) { statements } | convenience init(parameters) { statements } |
インスタンスコンストラクタを指定します。
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)")
上記プログラム実行出力は、次のとおりです。
res 为: 10 res 为: 10 res 为: 20
簡易コンストラクタの例
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)")
上記プログラム実行出力は、次のとおりです。
res 为: 20 res2 为: 30 res2 为: 50
継承とコンストラクタのオーバーロード
スウィフトサブクラスは親クラスのデフォルトコンストラクタを継承しません。
親クラスのコンストラクタは、唯一のケースの決意とセキュリティに継承されます。
あなたが親クラス指定されたコンストラクタをオーバーライドするときは、オーバーライド修飾子を記述する必要があります。
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)")
上記プログラム実行出力は、次のとおりです。
矩形: 4 边 五角型: 5 边
コンストラクタと利便コンストラクタの例を指定します。
次の例では、コンストラクタで指定された動作を実証コンストラクタと自動コンストラクタの継承を容易にします。
これは、2つのクラスに定義さMainClass、サブクラスクラス階層が含まれており、どのように自分のコンストラクタの相互作用を実証します。
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)")
上記プログラム実行出力は、次のとおりです。
MainClass 名字为: w3big 没有对应名字: [匿名] MainClass 名字为: w3big count 变量: 3
クラスのコンストラクタは失敗する可能性があります
クラス、オブジェクト、構造体、または列挙型が、それはプロセスが失敗に自分自身を構成することが可能である場合は、障害がコンストラクタを定義します。
変数の初期化に失敗しました考えられる理由は以下のとおりです。
受信パラメータ値が無効です。
必要ないくつかの外部リソースがありません。
これは、一定の条件を満たしていませんでした。
正しくこの構成プロセスのケースを処理するために失敗することがあります。
あなたは、構造体のクラス、または列挙型定義で、一つ以上の障害が発生したコンストラクタを追加することができます。 構文は、initキーワードJiatian(INIT?)の後に疑問符です。
例
次の例では、種を任命した動物と呼ばれる構造の定義、文字列型は、属性定数。
一方、構造は、コンストラクタを失敗する可能性が文字列型のパラメータ種と定義しています。 失敗する可能性がありますコンストラクタは、空の文字列、空の文字列に渡される引数は、コンストラクタは、オブジェクトを構築するために、失敗し、そうでなければ成功を失敗する可能性があるかどうかを確認するために使用されます。
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)") }
上記プログラム実行出力は、次のとおりです。
动物初始化为长颈鹿
列挙型のコンストラクタが失敗する可能性があります
あなたはコンストラクタによって設定することができる1つまたは複数のパラメータを持つことができ、列挙型、特定の列挙型メンバーを取得できませんでした。
例
次の例では、列挙型の定義はTemperatureUnitの名前。 これは三つの可能な列挙型のメンバー(ケルビン、摂氏、および華氏)が含まれており、障害が列挙メンバーを対応するコンストラクタ文字の値を見つけるために使用することができます。
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("这不是一个已定义的温度单位,所以初始化失败。") }
上記プログラム実行出力は、次のとおりです。
这是一个已定义的温度单位,所以初始化成功。 这不是一个已定义的温度单位,所以初始化失败。
クラスのコンストラクタは失敗する可能性があります
(構造体や列挙型など)値型は、コンストラクタを失敗する可能性があり、いつ、どこで建設は、この動作の制限なく失敗トリガします。
しかし、クラスのコンストラクタに障害が発生しても、エージェントはすべてのクラスの中でコンストラクタが点火障害時の動作後に初期化されているすべてのクラスのプロパティで発生した呼び出すことができます。
例
一例では、studnameプロパティが一定であるためStudRecordと呼ばれるクラスの定義は、StudRecordクラスのコンストラクタの成功一度ので、studnameプロパティが非nilの値を持っている必要があります。
class StudRecord { let studname: String! init?(studname: String) { self.studname = studname if studname.isEmpty { return nil } } } if let stname = StudRecord(studname: "失败构造器") { print("模块为 \(stname.studname)") }
上記プログラム実行出力は、次のとおりです。
模块为 失败构造器
コンストラクタをカバー失敗する可能性があります
他のコンストラクタと同じように、のような、あなたはまた、基底クラスのコンストラクタが失敗する可能サブクラスのコンストラクタで失敗する可能性が上書きすることができます。
あなたはまた、非コンストラクタサブクラスの故障で失敗する可能性がある基底クラスのコンストラクタによって上書きすることができます。
あなたは失敗する可能性がありますコンストラクタをカバーする非失敗したコンストラクタを使用することができますが、今度は、それは動作しません。
エージェントを呼び出すことはできません故障していないコンストラクタは、コンストラクタを失敗することがあります。
例
次の例では、障害と非障害コンストラクタについて説明します。
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) } }
上記プログラム実行出力は、次のとおりです。
行星的名字是: Mercury 没有这个名字的行星: [No Planets]
コンストラクタの初期化を失敗することがあります!
一般的に、我々は、キーワードのinit方法(initの?)の後に疑問符を追加するコンストラクタを定義するのに失敗することがありますが、あなたはまた、失敗したコンストラクタを定義するための方法の後に感嘆符を追加することにより、初期化を使用することができます(INITを!) 。 例としては、次のとおりです:
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("学生名为空") }
上記プログラム実行出力は、次のとおりです。
指定了学生名 学生名为空