Swift 6주차 과제

PepsiZero·2023년 10월 23일
0

Swift

목록 보기
6/9

1. 클로저

스위프트(Swift)에서 클로저(closure)는 일급 객체(first-class citizen)로서 다른 변수나 함수에 전달되거나 저장할 수 있는 코드 블록입니다. 클로저는 함수와 비슷한 역할을 하며, 주로 다음과 같은 상황에서 사용됩니다

(1) 함수를 변수나 상수에 저장: 클로저는 변수나 상수에 할당할 수 있으므로, 다른 코드에서 사용하거나 전달할 수 있습니다.

(2) 함수의 인자로 전달: 함수의 매개변수로 클로저를 전달하여 함수의 동작을 나중에 지정할 수 있습니다.

(3) 함수에서 반환: 함수의 반환값으로 클로저를 반환하여 다른 코드에서 사용할 수 있도록 합니다.

클로저의 기본 구조는 다음과 같습니다


{ (parameters) -> ReturnType in
    // 클로저의 실행 코드
    // 반환값이 있는 경우 "return" 키워드를 사용할 수 있습니다.
}

클로저에서 사용되는 주요 구성 요소는 다음과 같습니다

parameters: 클로저에 전달되는 매개변수 목록.
ReturnType: 클로저가 반환하는 값의 데이터 형식을 나타내며, 반환값이 없는 경우 Void로 지정합니다.
in: 클로저 매개변수와 실행 코드를 분리하는 키워드.

아래는 간단한 클로저 예제입니다


let add: (Int, Int) -> Int = { (a, b) in
    return a + b
}

let result = add(5, 3) // result는 8

위의 코드에서 add라는 클로저는 두 개의 정수를 입력받고, 더한 결과를 반환합니다. 그 후에 add 클로저를 호출하여 결과를 얻습니다.

클로저는 주로 다음과 같은 상황에서 사용됩니다

(1) 콜백 함수: 비동기 작업에서 완료 핸들러로 사용되며, 작업이 완료되면 클로저가 호출됩니다.

(2) 정렬 및 필터: 배열의 요소를 정렬하거나 필터링할 때 사용됩니다.

(3) 코드 블록 지정: 특정 동작을 함수에 전달할 때 유용합니다.

(4) 간단한 함수 대체: 작은 기능을 가진 함수를 따로 정의하지 않고 클로저로 대체할 수 있습니다.

클로저는 Swift의 강력한 기능 중 하나로, 코드를 간결하게 작성하고 다양한 상황에서 재사용 가능한 코드를 작성하는 데 도움을 줍니다.

1-1 일반 함수를 클로저로 변환


func add(x: Int, y: Int) -> Int {
    return x + y
}

// 함수를 클로저에 할당
let addClosure = { (x: Int, y: Int) -> Int in
    return add(x: x, y: y)
}

let result = addClosure(10, 20) // 30

위의 코드에서 add 함수를 addClosure라는 클로저에 할당하고, 클로저를 호출하여 같은 결과를 얻을 수 있습니다.

1-2 클로저를 일반 함수로 변환


let addClosure = { (x: Int, y: Int) -> Int in
    return x + y
}

// 클로저를 함수로 변환
func addFunction(x: Int, y: Int) -> Int {
    return addClosure(x, y)
}

let result = addFunction(x: 10, y: 20) // 30

1-3 일반 함수를 클로저로 변환 (후행 클로저 사용)

func add(x: Int, y: Int, operation: (Int, Int) -> Int) -> Int {
    return operation(x, y)
}

let result = add(x: 10, y: 20) { $0 + $1 }
print(result) // 30

위의 코드에서 add 함수는 두 정수를 인자로 받는 함수입니다. operation 매개변수에 클로저를 전달하고, 후행 클로저를 사용하여 클로저를 간단하게 정의합니다. 이렇게 하면 함수 호출이 간결해집니다.

1-4 클로저를 일반 함수로 변환 (후행 클로저 사용)


func addFunction(x: Int, y: Int, operation: (Int, Int) -> Int) -> Int {
    return operation(x, y)
}

let addClosure = { (x: Int, y: Int) -> Int in
    return x + y
}

let result = addFunction(x: 10, y: 20, operation: addClosure)
print(result) // 30

2. 클래스

클래스의 프로퍼티(변수)를 선언할 때, 기본적으로 초기값을 지정해야 합니다. 이 초기값이 클래스의 객체가 생성될 때 사용됩니다. 초기값이 없는 프로퍼티를 선언하려면 옵셔널을 사용하거나, 이니셜라이저(생성자)를 통해 초기화해야 합니다. 이렇게 초기값이 필요한 이유는 객체가 항상 유효한 상태로 시작하도록 보장하기 위함입니다.

class MyClass {
    var value: Int = 0 // 초기값 지정
}

왜 사용하나요?: 초기값을 지정함으로써 객체를 안전하게 초기화하고, 코드를 더 예측 가능하게 만듭니다.

옵셔널 프로퍼티와 이니셜라이저:

옵셔널 프로퍼티: 클래스나 구조체에서 초기값이 필요 없는 프로퍼티를 정의하려면 옵셔널을 사용할 수 있습니다. 이는 값이 존재하지 않을 수 있다는 의미입니다.


class MyClass {
    var value: Int? // 옵셔널로 선언
}

이니셜라이저: 초기값 없이 프로퍼티를 정의할 때, 객체가 생성될 때 값을 할당하는 특별한 메서드를 사용합니다.


class MyClass {
    var value: Int
    
    init(initialValue: Int) {
        value = initialValue
    }
}

왜 사용하나요?: 옵셔널은 값이 없을 수 있는 상황에 유용하며, 이니셜라이저는 초기화 과정을 제어하고 객체를 올바르게 설정할 수 있습니다.

오버로딩(Overloading)과 오버라이딩(Overriding):

오버로딩(Overloading): 클래스나 구조체 내에서 같은 이름의 함수나 메서드를 여러 개 정의하는 것을 말합니다. 다만, 각각의 함수는 다른 매개변수 형식, 개수 또는 반환 값 형식을 가져야 합니다.


class Calculator {
    func add(x: Int, y: Int) -> Int {
        return x + y
    }
    
    func add(x: Double, y: Double) -> Double {
        return x + y
    }
}

오버라이딩(Overriding): 상속 관계에서, 부모 클래스에서 정의된 메서드를 자식 클래스에서 재정의하는 것을 말합니다. 재정의된 메서드는 부모 클래스의 메서드 대신 호출됩니다.


class Vehicle {
    func startEngine() {
        print("Engine started")
    }
}

class Car: Vehicle {
    override func startEngine() {
        print("Car engine started")
    }
}

왜 사용하나요?: 오버로딩은 메서드의 다형성을 지원하고, 오버라이딩은 상속된 메서드를 수정하여 자식 클래스의 특수한 동작을 구현하는 데 사용됩니다. 이를 통해 코드 재사용과 유연성을 증가시킬 수 있습니다.

profile
존나 버틴놈이 존나 성공한다.

0개의 댓글