[250318] 트레일링 클로저, class와 struct

ON&OFF·2025년 3월 18일

iOS TIL

목록 보기
5/18

트레일링 클로저란?

  • 함수의 마지막 매개변수(파라미터)가 클로저(Closure)일 때, 함수 호출 괄호 () 바깥에 클로저를 작성하는 문법
  • 가독성이 좋아지고, 코드를 깔끔하게 작성할 수 있다.

(1) 일반적인 클로저 사용 방식

func calculate(a: Int, b: Int, operation: (Int, Int) -> Int) -> Int {
    return operation(a, b)
}
let result = calculate(a: 10, b: 5, operation: { (x, y) in
    return x + y
})
print(result) // 15

(2) 트레일링 클로저(Trailing Closure) 사용 방식

let result = calculate(a: 10, b: 5) { (x, y) in
    return x + y
}
print(result) // 15
  • 여기서 operation 매개변수가 마지막이기 때문에, () 바깥에서 클로저를 작성할 수 있다.

class

  • 프로퍼티와 메소드로 구성되어있다.

    • class 안에 있는 변수,상수를 프로퍼티라 한다.
    • class 안에 있는 함수를 메소드라고 한다.
  • class의 인스턴스를 생성할 때 반드시 초기화를 해줘야 한다.

    • init 초기화를 제공해야 한다.
      // 일반적인 init
      class Person {
       var name: String // 값을 저장하는 저장 프로퍼티
       var age: Int
       init(name: String, age: Int) {
           self.name = name
           self.age = age
       }
      }
      let person = Person(name: "Brody", age: 25)
    • 모든 프로퍼티에 default 값을 제공한다면 init 초기화를 생략할 수 있습니다.
class Person {
    var name: String = "이름없음"
    var age: Int = 0
}
let person = Person()
// 혹은 파라미터를 받지 않는 init에서 모든 프로퍼티 값을 정해줄 수 있습니다.
class Person {
    var name: String
    var age: Int
    init() {
        self.name = "이름없음"
        self.age = 15
    }
 }
  • 모든 프로퍼티가 Optional 인 경우 init 초기화를 생략할 수 있습니다.
  • 여러가지 init 을 만들면 여러가지 방법으로 class를 초기화할 수 있습니다.
    class Person {
     var name: String
     var age: Int
     init(name: String, age: Int) {
         self.name = name
         self.age = age
     }
     init(name: String) {
         self.name = name
         self.age = 0
     }
     init() {
         self.name = "이름없음"
         self.age = 15
     }
    }
  • class를 사용해서 만들어진 인스턴스는 Reference Type 입니다.
    • 인스턴스를 let 으로 만들어도 프로퍼티 변경이 된다.
    • 함수에 class의 인스턴스를 전달하고 프로퍼티를 변경하면 원본도 변경이 됩니다.
  • 상속 가능
    • 하위클래스가 상위클래스의 속성(프로퍼티)와 행동(메소드)를 물려받아서 사용할 수 있습니다.
  • 초기화를 도와주는 컨비니언스 이니셜라이저(convenience initializer)를 제공합니다.
// 컨비니언스 이니셜라이저(convenience initializer) 사용해보기
// 파라미터에 값을 할당하지 않고 컨비니언스 이니셜라이즈를 사용해도 비슷한 효과를 낼 수 있습니다.
class Person {
    var name: String
    var age: Int // 기본값을 주지 않았어요!
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    convenience init(name: String) { // convenience init에서 name만 받은 후 아래 init에서 기본값을 정해줄 수 있습니다.
        self.init(name: name, age: 0)
    }
}
let person = Person(name: "이름만 있어요!")
print(person.age) // 0 
  • 소멸자(deinit)가 존재한다.
    • class 에서만 사용 가능합니다.
    • 사용이 종료된 인스턴스가 메모리에서 해제될 때 자동 호출됩니다.
    • 직접 호출은 할 수 없습니다.
      deinit {
      	// 구현부 
      }

Struct

  • 프로퍼티와 메소드로 구성되어 있다.
  • Memberwise Initializer(멤버와이즈 이니셜라이저)를 제공합니다.
    • 직접 init 을 정의하지 않아도 모든 프로퍼티의 초기화를 자동으로 생성해주는 기능이에요.
  • 구조체를 사용하여 만들어진 인스턴스는 Value Type 입니다.
    • 구조체의 인스턴스는 값이 복사 되므로, 서로 다른 값으로 처리됩니다.
  • 메소드에서 프로퍼티를 변경하려면 mutating 키워드를 사용해야 됩니다.
  • 상속 불가능
    • 클래스와 달리 구조체는 다른 구조체로부터 상속받거나 상속할 수 없습니다.
  • 인스턴스를 let 으로 만들면 내부 프로퍼티 변경할 수 없습니다.
    프로퍼티를 변경하려면 var 로 만들어야 합니다.

느낀 점

가독성을 위해 사용하는 건데 낯설다.. 클로저라는 개념이 아직 명확히 잡히지 않은 것 같고 class와 struct도 비슷한 듯 달라서 공부가 더 필요할 것 같다..😭

profile
안 되면 될 때까지

0개의 댓글