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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

area is: 180.0
area is: 370.0
area is: 110.0

선택적 속성 유형

어떤 인스턴스에 저장된 속성이 값을 반환하지 않으면 해당 속성은 해당 특정 유형에 대해 '값 없음'이 반환됨을 나타내는 '선택적'유형으로 선언됩니다. 저장된 속성이 'optional'로 선언되면 초기화 자체에서 값이 '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)")

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

초기화 중 상수 속성 수정

초기화를 통해 사용자는 상수 속성 값도 수정할 수 있습니다. 초기화 중에 클래스 속성을 사용하면 클래스 인스턴스를 하위 클래스가 아닌 수퍼 클래스가 수정할 수 있습니다. 예를 들어 이전 프로그램에서 '길이'는 메인 클래스에서 '변수'로 선언되었습니다. 아래 프로그램 변수 'length'는 'constant'변수로 수정됩니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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'클래스 명으로 정의되어 있습니다. 세 가지 멤버 함수는 기본적으로 '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)")

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

이니셜 라이저 위임 규칙

값 유형 클래스 유형
구조 및 열거와 같은 값 유형에 대해서는 상속이 지원되지 않습니다. 다른 이니셜 라이저 참조는 self.init를 통해 수행됩니다. 상속이 지원됩니다. 저장된 모든 속성 값이 초기화되었는지 확인합니다.

클래스 상속 및 초기화

클래스 타입은 정의 된 저장 속성이 초기 값을 받는지 확인하기위한 두 종류의 이니셜 라이저, 즉 지정된 이니셜 라이저와 편의 이니셜 라이저가 있습니다.

지정된 이니셜 라이저 및 편의 이니셜 라이저

지정된 이니셜 라이저 편의 이니셜 라이저
클래스의 기본 초기화로 간주 클래스에 대한 초기화 지원으로 간주
모든 클래스 속성이 초기화되고 추가 초기화를 위해 적절한 수퍼 클래스 이니셜 라이저가 호출됩니다. 지정된 이니셜 라이저는 편의 이니셜 라이저와 함께 호출되어 특정 사용 사례 또는 입력 값 유형에 대한 클래스 인스턴스를 생성합니다.
모든 클래스에 대해 하나 이상의 지정된 이니셜 라이저가 정의됩니다. 클래스에 이니셜 라이저가 필요하지 않은 경우 편의 이니셜 라이저를 강제로 정의 할 필요가 없습니다.
Init (매개 변수) {문} 편의 init (매개 변수) {문}

지정된 이니셜 라이저를위한 프로그램

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

실패한 초기화 프로그램

사용자는 클래스, 구조 또는 열거 형 값을 정의하는 동안 초기화 오류가 발생하면이를 알려야합니다. 변수 초기화는 때때로 다음과 같은 이유로 실패합니다.

  • 잘못된 매개 변수 값입니다.
  • 필요한 외부 소스가 없습니다.
  • 초기화가 성공하지 못하는 상태입니다.

초기화 메서드에서 발생하는 예외를 포착하기 위해 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")
}

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

Module is Optional("Failable Initializers")

실패 할 수있는 이니셜 라이저 재정의

초기화와 마찬가지로 사용자는 하위 클래스 내에서 수퍼 클래스 실패 가능한 이니셜 라이저를 재정의 할 수 있습니다. 실패 할 수있는 수퍼 클래스 초기화는 실패 할 수없는 이니셜 라이저 하위 클래스에서 재정의 할 수도 있습니다.

실패 할 수없는 서브 클래스 초기화로 실패 가능한 슈퍼 클래스 초기화자를 재정의 할 때 서브 클래스 초기화 프로그램은 슈퍼 클래스 초기화 프로그램까지 위임 할 수 없습니다.

실패 할 수없는 이니셜 라이저는 실패 할 수있는 이니셜 라이저에 위임 할 수 없습니다.

아래에 제공된 프로그램은 실패 할 수있는 이니셜 라이저와 실패 할 수없는 이니셜 라이저를 설명합니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

초기화! 실패한 초기화 프로그램

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

10
30
10