ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Initializer 1편 (Struct의 Initializer)
    오늘의 Swift 상식 2021. 8. 8. 00:48
    728x90
    반응형

     

     

     

     

     

     

     


     

     

     

    안녕하세요. iOS 개발자 에이든입니다!👦🏻

     

     

     

    이번 시간은 Initializer에 대해 알아보겠습니다!

    처음 객체를 생성할 때 쓰이는 아주 중요한 녀석이죠!

    지난 시간에 Struct, Class에 대해서 알아보셨죠?

    이 둘은 Initializer를 쓰는 법도 조금 다르답니다.

     

     

     

    자 그럼 Initializer 첫 번째 시간!

    Initiazlier의 기본 부터

    Struct의 Initializer까지 한번 알아봅시다

    따라오시죠!!!

     

     


     

     

     

    일단 초기화의 개념에 대해 먼저 알고 가보죠

    쉽게 말해 공장 초기화 아시죠?

    초기에 이 상품이 나올 때의 상태로 세팅하는 것과 같다고 보시면 될 것 같아요!

     

     

    공장에서 나오는 제품처럼 Class, Struct, Enum 등의 Instance를 처음 생성할 때 필요한 값들을 넣어주는 과정입니다.

    맥이나 아이폰 처음 나올 때 특정 버전의 OS가 들어가는 것처럼요ㅎㅎ

    적절한 비유가 됐는지 모르겠네요 ~.~

     

     

    추가 적인 설명을 드리자면

    1. Class, Struct, Enum 등의 Instance를 사용하기 위한 준비 작업
    2. Property초기값을 설정하는 과정
    3. 초기화 작업이 완료되면 메모리에 Instance가 생성

     

     

     

    이런 초기화를 하기 위한 녀석이 바로 Initializer이구요! 사용법은 아래와 같답니다~

    init() {
        // 이 곳에 초기화를 구현
    }
    
    // Instance를 생성할때는 아래와 같이 init을 생략할 수 있어요!
    let student = Student(name: "aiden")
    let student = Student.init(name: "aiden")

     

     

     

    자 그럼 초기화하는 방법을 하나하나씩 볼까요?

     

     

     


    1. 기본 값을 지정하여 초기화하는 방법 

    Property 선언과 동시에 값을 할당해버리면 따로 초기화를 할 필요가 없게 됩니다.
    항상 같은 초기 값을 가진다면 이 방법이 좋아요!
    Struct People {
    	let name = "Aiden"
    	let info = "iOS Developer"
    }

     

     

     

     

     


    2. Initializer를 사용하여 초기화 하는 방법

    Initializer는 Method와 달리 괄호 앞에 식별할 수 있는 이름이 없기 때문에 매개 변수명과 Type이 Initializer들을 식별하는 데에 아주 중요한 역할을 한답니다. 문법은 흔히 우리가 사용하는 Method와 같아요!
    struct Sample {
    
        ...
    
        // 외부 이름과 내부 이름을 준 경우
        init(tall height: Double) {...}
        
        // 인자명을 지정하지 않으면 내부 이름과 동일한 외부 이름을 가집니다.
        init(weight: Double) {...}
        
        // 인자명을 생략하고 싶다면 '_'(와일드 카드)를 사용하면 됩니다.
        init(_ footSize: Int) {...}
    }
    
    let sample1 = Sample(tall: 182.8)
    let sample2 = Sample(weight: 77.5)
    let sample3 = Sample(270)

     

     

    • Optional Type
    Property를 Optionnal Type으로 선언한 경우 초기값이 없어도 되고, 나중에 추가도 가능합니다! 초기값이 없는 경우에는 자동적으로 nil로 초기화된답니다!
    Struct People {
    
        var weight: Double?
        var footSize: Int
        
        init(footSize: Int) {
        	self.footSize = footSize
        }
    }
    
    var aiden = People(footSize: 270)
    print(aide) // People(weight: nil, footSize: 270)
    aiden.weight = 76.7
    print(aiden) // People(weight: Optional(76.7), footSize: 270)

     

    • 상수 Property
    상수는 값을 바꿀 수 없다는 법칙은 Initializer에게 통하지 않습니다!! 상수 Property에 값을 할당하는 것도 가능하죠! 단, 값이 없어야 하고 값이 들어간 후에는 여전히 바꿀 수 없답니다.
    struct People {
    
        let footSize: Int
        
        init(footSize: Int) {
        	self.footSize = footSize
        }
    }
    
    let aiden = People(footSize: 270)
    print(aiden) // People(footSize: 270)

     

     

    • 실패 가능한 Initializer
    초기화 과정 중에 실패할 가능성이 있는 Initializer도 만들 수 있어요. 반환 값으로 Optional을 반환하고, 초기화 실패 시 nil을 반환합니다.
    struct People {
    	
        let footSize: String
        
        init?(footSize: String) {
        	if footSize.isEmpty { return nil }
            self.footSize = footSize
        }
    }

    !! 앞서 말씀드렸듯이 Initializer는 매개변수명과 Type으로 구분하기 때문에 실패 가능한 Initializer와 그렇지 않은 Initializer의 형태가 다르다고 해서 같은 매개변수 Type과 이름을 사용할 수 없습니다. 주의하세요ㅎㅎ

     

     

     

     

    자! Initializer에 대해 간단히 알아보았습니다!

    그럼 Struct에서 Initializer가 어떻게 사용되는지 살펴보고

    같은 값 Type인 Enum에서도 Initializer가 어떻게 사용되는지 살펴 봅시당!


    Struct's Initializer

     

    • 종류

    1. Memberwise Initializer

    Property를 매개 변수로 가지는 Initializer
    1. Struct 내에 Property가 하나라도 초기화되지 않은 경우, 초기값이 없는 속성을 매개 변수로 갖는 Memberwise Initializer가 제공됩니다.

    2. 속성이 모두 let으로 값까지 모두 초기화되어있는 경우 Memberwise Initializer 제공되지 않습니다. 

     

    2. 기본 Initializer

    매개 변수 X
    1. Property가 모두 초기화 되어 있는 경우 매개 변수가 없는 Initializer가 제공됩니다.
    struct Sample {
        let string: String
        let int: Int
        let bool: Bool
    }
    
    let sample = Sample(string: "하하") // Memberwise Initializer
    
    // =====================================================================
    
    struct Sample {
        var string: String = "하하"
    }
    
    let sample = Sample() // 기본 Initializer
    let sample2 = Sample(string: "호호") // Memberwise Initializer
    
    // =====================================================================
    
    struct Sample {
        let string = "하하"
    }
    
    let sample = Sample()
    let sample2 = Sample(string: "호호") // !Error: let으로 선언되었기 때문에 값 변경 불가

     

     

    • Initializer Ddelegation
    쉽게 말해 Initializer를 위임한다고 보시면 돼요. Initializer는 Instance 초기화의 일부를 수행하기 위해 다른 Initializer를 호출할 수도 있답니다!
    struct Frame {
    
        var x: Int
        var y: Int
        
        init(x: Int, y: Int) {
        	self.x = x
            self.y = y
        }
        
        init(y: Int) {
        	self.init(x: 0, y: y) // 다른 Initializer 호출
        }
    }
    
    let rect = Frame(x: 10, y: 8)
    let originRect = Frame(y: 5)

     

     

     

     

     


    Enum's Initializer

    1. Enum은 rawValue가 있는 경우 rawValue로부터 Instance를 생성할 수 있는 실패 가능한 initializer가 기본으로 제공됩니다.

    2. Enum의 case들을 초기화해주는 것은 가능하지만 rawValue는 변할 수 없는 값이기 때문에 초기화해줄 수 없어요ㅜ 명심!!

    enum PowerRanger: String {
        case red
        case blue = "블루"
        case black
        
        init(call: Character) {
        	switch call {
                case "r", "R": 
                	self = .red
                case "b", "B":
                	self = .blue
                default:
                	self = .black
            }
        }
    }
    
    let callToDoctor = PowerRanger(call: "R") // red
    let callToDoctor2 = PowerRanger(rawValue: "레드") // nil
    let callToDoctor3 = PowerRanger(rawValue: "블루") // blue

     

     

     

     

     


    값 Type의 Initializer Extension

    Extension 본연의 의미 그대로 처음에 구현하지 않고, 뒤에 Initializer를 추가적으로 구현할 수도 있어요!
    struct People {
        var name: String
        var footSize: Int
        
        init(name: String, footSize: Int) {
            self.name = name
            self.footSize = footSize
        }
    }
    
    extension People {
        // Initializer는 매개 변수의 이름으로 식별하기 때문에 이름이나 Type을 다르게 해줘야 합니다.
        init(footSize: Int) {
            self.name = "aiden"
            self.footSize = footSize + 10
        }
    }
    
    let people = People(name: "0131", footSize: 270) // People(name: "0131", footSize: 270)
    let aiden = People(footSize: 270) // People(name: "aiden", footSize: 280)

     

     


     

     

    자 이번 시간에는 Struct의 Initializer와 Enum의 Initializer에 대해 알아보았습니다!

    저도 무의식적으로 그냥 init()의 기본적인 형태만 사용했었는데

    다시 보니 감회도 새롭고 다양한 상황에 맞춰 잘 사용해야겠다는 생각이 드네요ㅎㅎ

    다음 편은 Class의 Initializer에 대해 공부해보겠습니다!

     

     

    혹시라도 부족하거나 잘못된 부분 그리고 질문 있으시면 언제든 댓글 부탁드려요! 감사합니다!👦🏻👋🏻

     

    728x90
    반응형

    '오늘의 Swift 상식' 카테고리의 다른 글

    Protocol 1편 (Protocol 정의 방법)  (0) 2021.08.16
    Class의 상속  (0) 2021.08.15
    Initializer 2편 (Class의 Initializer)  (0) 2021.08.08
    Struct, Class  (2) 2021.07.18
    iOS 앱 생명주기  (3) 2021.07.14

    댓글

Designed by Tistory.