Swift-initialization

提供:Dev Guides
移動先:案内検索

Swift-初期化

Swift 4で宣言されたクラス、構造、および列挙は、クラスのインスタンスを準備するために初期化されます。 格納されたプロパティの初期値が初期化され、新しいインスタンスの初期値も初期化され、さらに先に進みます。 初期化関数を作成するためのキーワードは、「init()」メソッドによって実行されます。 Swift 4初期化子は、値を返さないという点でObjective-Cと異なります。 その機能は、処理前に新しく作成されたインスタンスの初期化をチェックすることです。 Swift 4は、インスタンスの割り当てが解除されると、メモリ管理操作を実行するための「初期化解除」プロセスも提供します。

格納されたプロパティの初期化ロール

格納されたプロパティは、インスタンスを処理する前に、クラスと構造のインスタンスを初期化する必要があります。 格納されたプロパティは、イニシャライザを使用して値を割り当てて初期化し、プロパティオブザーバを呼び出す必要をなくします。 保存されたプロパティで初期化子が使用されます

  • 初期値を作成します。
  • プロパティ定義内でデフォルトのプロパティ値を割り当てます。
  • 特定のデータ型のインスタンスを初期化するには、「init()」を使用します。 init()関数内では引数は渡されません。

構文

init() {
  //New Instance initialization goes here
}

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

area of rectangle is 72.0

ここで、構造 'rectangle’は、メンバーの長さと幅を 'Double’データ型として初期化されます。 Init()メソッドは、新しく作成されたメンバーlengthおよびdoubleの値を初期化するために使用されます。 四角形の面積は、四角形関数を呼び出して計算され、返されます。

デフォルトでプロパティ値を設定する

Swift 4言語は、格納されているプロパティ値を初期化するInit()関数を提供します。 また、ユーザーは、クラスまたは構造体のメンバーを宣言するときに、デフォルトでプロパティ値を初期化するためのプロビジョニングを持っています。 プロパティがプログラム全体で同じ値のみをとる場合、init()で初期化するのではなく、宣言セクションで単独で宣言できます。 デフォルトでプロパティ値を設定すると、クラスまたは構造に継承が定義されているときにユーザーが有効になります。

struct rectangle {
   var length = 6
   var breadth = 12
}

var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

area of rectangle is 72

ここで、init()で長さと幅を宣言する代わりに、値は宣言自体で初期化されます。

パラメータの初期化

Swift 4言語では、ユーザーは、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)")

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

area is: 72.0
area is: 432.0

ローカルおよび外部パラメーター

初期化パラメーターには、関数およびメソッドのパラメーターと同様のローカルおよびグローバルのパラメーター名があります。 ローカルパラメータ宣言は初期化本体内のアクセスに使用され、外部パラメータ宣言は初期化子の呼び出しに使用されます。 Swift 4初期化子は、どの関数を呼び出すためにどの初期化子が使用されるかを識別しないという点で、関数およびメソッドの初期化子と異なります。

これを克服するために、Swift 4はinit()の各パラメーターに自動外部名を導入します。 この自動外部名は、すべての初期化パラメーターの前に記述されたローカル名と同等です。

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

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

外部名のないパラメーター

アンダースコアの初期化に外部名が必要ない場合、デフォルトの動作をオーバーライドするために「_」が使用されます。

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

area is: 180.0
area is: 370.0
area is: 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("area is: \(rectarea.length)")

let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")

let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

初期化中の定数プロパティの変更

また、初期化により、ユーザーは定数プロパティの値も変更できます。 初期化中に、クラスプロパティを使用すると、サブクラスではなくスーパークラスによってクラスインスタンスを変更できます。 たとえば、前のプログラムで、「長さ」がメインクラスで「変数」として宣言されていることを考慮してください。 以下のプログラム変数「長さ」は「定数」変数として変更されます。

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

デフォルトの初期化子

デフォルトの初期化子は、デフォルト値を持つ基本クラスまたは構造体のすべての宣言されたプロパティに新しいインスタンスを提供します。

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます。 −

result is: nil
result is: 98
result is: true

上記のプログラムは、クラス名を「defaultexample」として定義されています。 3つのメンバー関数は、デフォルトで「studname?」として初期化されます「nil」値、「stmark」を98、「pass」をブール値「true」として保存します。 同様に、クラスのメンバータイプを処理する前に、クラスのメンバー値をデフォルトとして初期化できます。

構造型のメンバーごとの初期化子

カスタム初期化子がユーザーによって提供されない場合、Swift 4の構造型は自動的に「メンバーごとの初期化子」を受け取ります。 その主な機能は、デフォルトのメンバーごとの初期化で新しい構造体インスタンスを初期化することです。その後、新しいインスタンスプロパティが名前ごとにメンバーごとに初期化されます。

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

Area of rectangle is: 24.0
Area of rectangle is: 32.0

構造体は、「長さ」を「100.0」、「幅」を「200.0」として初期化するときに、メンバーシップ関数に対してデフォルトで初期化されます。 ただし、変数の長さおよび幅の処理中、値は24.0および32.0としてオーバーライドされます。

値型の初期化子委任

初期化子委任は、他の初期化子から初期化子を呼び出すこととして定義されます。 その主な機能は、複数の初期化子間でのコードの重複を回避するための再利用性として機能することです。

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

(0.0,0.0) (0.0,0.0)
(2.0,2.0) 5.0,5.0)
(2.5,2.5) (3.0,3.0)

初期化子委任のルール

Value Types Class Types
Inheritance is not supported for value types like structures and enumerations. Referring other initializers is done through self.init Inheritance is supported. Checks all stored property values are initialized

クラスの継承と初期化

クラス型には、定義された保存済みプロパティが初期値、つまり指定された初期化子と便利な初期化子を受け取るかどうかを確認するための2種類の初期化子があります。

指定された初期化子と便利な初期化子

Designated Initializer Convenience Initializer
Considered as primary initializes for a class Considered as supporting initialize for a class
All class properties are initialized and appropriate superclass initializer are called for further initialization Designated initializer is called with convenience initializer to create class instance for a specific use case or input value type
At least one designated initializer is defined for every class No need to have convenience initializers compulsory defined when the class does not require initializers.
Init(parameters) \{ statements } convenience init(parameters) \{ statements }

指定された初期化プログラム

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

res is: 10
res is: 10
res is: 20

便利な初期化プログラム

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

res is: 20
res is: 30
res is: 50

初期化子の継承とオーバーライド

Swift 4では、デフォルトでは、サブクラスがそのメンバータイプのスーパークラス初期化子を継承することを許可していません。 継承は、自動イニシャライザの継承で説明するある程度まで、スーパークラスのイニシャライザにのみ適用できます。

ユーザーがスーパークラスで初期化子を定義する必要がある場合、初期化子を持つサブクラスをカスタム実装としてユーザーが定義する必要があります。 サブクラスによってオーバーライドが行われる必要がある場合、スーパークラスの 'override’キーワードを宣言する必要があります。

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

Rectangle: 4 sides
Pentagon: 5 sides

動作中の指定および便利な初期化子

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

Planet name is: Mercury
No Planets like that: [No Planets]

Failable Initializer

ユーザーは、クラス、構造、または列挙値の定義中に初期化子の障害が発生したときに通知を受ける必要があります。 変数の初期化が原因で失敗することがあります-

  • 無効なパラメーター値。
  • 必要な外部ソースがありません。
  • 初期化の成功を妨げる条件。

初期化メソッドによってスローされた例外をキャッチするために、Swift 4は「failable initializer」と呼ばれる柔軟な初期化を生成し、構造体、クラス、または列挙メンバーの初期化中に何かが気付かれていないことをユーザーに通知します。 失敗可能な初期化子をキャッチするキーワードは「init?」です。 また、フェイル可能イニシャライザとフェイル不可イニシャライザを同じパラメータタイプと名前で定義することはできません。

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

Student name is specified
Student name is left blank

列挙の失敗可能な初期化子

Swift 4言語は、列挙型メンバーが値の初期化を終了したときにユーザーに通知するために、列挙型のFailableイニシャライザーを使用する柔軟性を提供します。

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

With In Block Two
Block Does Not Exist

クラスの失敗可能な初期化子

列挙型および構造体で宣言された失敗可能な初期化子は、その実装内の任意の状況で初期化の失敗を警告します。 ただし、クラスの失敗可能な初期化子は、保存されたプロパティが初期値に設定された後にのみ失敗を警告します。

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

Module is Optional("Failable Initializers")

Failable Initializerのオーバーライド

初期化のように、ユーザーは、サブクラス内のスーパークラスのフェイル可能なイニシャライザーをオーバーライドする機能も備えています。 スーパークラスのフェイル可能初期化は、サブクラスのフェイル不可初期化子でオーバーライドすることもできます。

サブクラス初期化子は、失敗しないサブクラス初期化で失敗するスーパークラス初期化子をオーバーライドする場合、スーパークラス初期化子まで委任できません。

失敗しない初期化子は、失敗する初期化子に委任することはできません。

以下のプログラムは、フェイル可能イニシャライザーとフェイル不可イニシャライザーについて説明しています。

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

Planet name is: Mercury
No Planets like that: [No Planets]

初期化! Failable Initializer

Swift 4は「init?」を提供しますオプションのインスタンス失敗可能イニシャライザを定義します。 特定のタイプ「init!」の暗黙的にアンラップされたオプションのインスタンスを定義するには指定されます。

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

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

Student name is specified
Student name is left blank

必要な初期化子

initialize 'required’キーワードの各サブクラスを宣言するには、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()

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

10
30
10