Swift 3주차 과제

PepsiZero·2023년 9월 20일
0

Swift

목록 보기
3/9

1. 옵셔널이란?

Swift에서 옵셔널(Optional)은 변수에 값이 있는지 없는지 구분하기 위해 사용하는 방식입니다. 모든 타입을 옵셔널로 선언할 수 있으며, 타입 뒤에 물음표(?)를 추가하여 옵셔널로 설정합니다. Swift에서 옵셔널을 선언하는 방법은 다음과 같습니다.

// 변수나 상수의 타입 뒤에 물음표(?)를 추가하여 옵셔널로 선언합니다.

var name: String?

// 함수의 반환 값을 옵셔널로 선언하려면 함수의 반환 타입 뒤에 물음표(?)를 추가합니다.

func getName() -> String? {
  // 코드
  return name
}
// 매개변수를 옵셔널로 선언하려면 매개변수의 타입 뒤에 물음표(?)를 추가합니다.
func setName(name: String?) {
  // 코드
}

옵셔널 변수는 일반적인 값을 가질 수도 있고, nil 값을 가질 수도 있습니다. nil 값을 변수에 넣기 위해서는 변수를 옵셔널로 선언해야 합니다.

1-1 nil 이란?

nill은 널(null) 값을 나타내는 값으로, 변수에 값이 할당되지 않았거나, 존재하지 않는 값을 의미합니다. Swift에서는 모든 변수가 반드시 값을 가져야 하기 때문에, 변수에 값이 없을 경우를 대비하여 옵셔널(Optional) 타입을 사용합니다. 옵셔널 타입의 변수는 값이 있을 경우에는 일반적인 값을 저장하고, 값이 없을 경우에는 nil 값을 저장합니다.

1-2 옵셔널을 해제하는 여러가지 방법

(1)unwrap: 옵셔널 변수의 값을 추출하는 방법입니다. ! 연산자를 사용하여 값을 추출합니다. 만약 값이 nil인 경우에는 예외가 발생합니다.

let name = user?.name!

(2)optional binding: 옵셔널 변수의 값을 추출하는 방법입니다. if let 구문을 사용하여 값을 추출합니다. 만약 값이 nil인 경우에는 해당 구문을 실행하지 않고 다음 코드로 이동합니다.

if let name = user?.name {
  print(name)
}

(3)optional chaining: 옵셔널 변수의 값을 연쇄적으로 추출하는 방법입니다. ? 연산자를 사용하여 값을 추출합니다. 만약 값이 nil인 경우에는 다음 값을 추출하지 않고 nil을 반환합니다.

let age = user?.name?.age

(4)force unwrapping: 옵셔널 변수의 값을 강제로 추출하는 방법입니다. ! 연산자를 사용하여 값을 추출합니다. 만약 값이 nil인 경우에는 예외가 발생합니다.

let age = user!.name!.age!

위의 방법 중에서 가장 안전한 방법은 optional binding입니다. 값이 nil인 경우에는 해당 구문을 실행하지 않고 다음 코드로 이동하기 때문에, 예외가 발생하지 않습니다

1-3 옵셔널 바인딩

옵셔널 바인딩(Optional Binding)은 Swift에서 옵셔널(Optional) 타입의 값을 안전하게 추출하는 방법입니다. 옵셔널 바인딩을 사용하면 옵셔널 값이 nil인지 아닌지를 확인하고, 값이 있으면 해당 값을 추출하여 다른 변수나 상수에 할당할 수 있습니다.

옵셔널 바인딩에는 if-letguard-let 두 가지 방식이 있습니다.

(1)if-let 방식

if-let 구문을 사용하여 옵셔널 값이 nil이 아닌 경우, 해당 값을 추출하여 다른 변수나 상수에 할당합니다.

if let name = user?.name {
  print(name)
}

(2)guard-let 방식

guard-let 구문을 사용하여 옵셔널 값이 nil이 아닌 경우, 해당 값을 추출하여 다른 변수나 상수에 할당합니다. 만약 값이 nil인 경우에는 해당 구문을 실행하지 않고 다음 코드로 이동합니다.

guard let name = user?.name else {
  return
}

print(name)

옵셔널 바인딩을 사용하면 옵셔널 값이 nil인지 여부를 확인하고, 값이 있는 경우에만 해당 값을 추출하여 사용할 수 있으므로, 오류를 예방할 수 있습니다.

2. 결합성과 우선순위

  1. 우선순위: 연산자의 우선순위는 연산자가 수행되는 순서를 결정합니다. 예를 들어, 더하기 연산자와 곱하기 연산자가 있을 때, 곱하기 연산자가 더 높은 우선순위를 가지므로 먼저 수행됩니다.
  2. 결합성: 연산자의 결합성은 연산자가 두 개 이상의 피연산자를 가지는 경우에 적용됩니다. 예를 들어, 더하기 연산자는 왼쪽에서 오른쪽으로 결합성이 있으므로, 왼쪽에 있는 피연산자부터 먼저 계산됩니다.
let x = 10
let y = 20
let z = x + y * 2

print(z) // 50

2-1 증감 연산자, 감소 연산자

증감 연산자와 감소 연산자는 변수의 값을 증가시키거나 감소시키는 데 사용되는 연산자입니다. 스위프트에서는 후위 증가 연산자(++)와 후위 감소 연산자(--)가 제공되지 않습니다. 그 대신에 증가 연산자(+=)와 감소 연산자(-=)를 사용하여 값을 증가시키거나 감소시킵니다.

증가 연산자 (+=):

증가 연산자는 변수의 값을 증가시킵니다. 이 연산자는 현재 변수의 값에 다른 값을 더하여 변수에 할당합니다.

var number = 5
number += 2 // number의 값을 2 증가시킴
print(number) // 출력: 7

감소 연산자 (-=):

감소 연산자는 변수의 값을 감소시킵니다. 이 연산자는 현재 변수의 값에서 다른 값을 뺀 후 변수에 할당합니다.

var number = 8
number -= 3 // number의 값을 3 감소시킴
print(number) // 출력: 5

스위프트 3 이후로 변수에 값을 주고 변수++ 또는 변수--와 같이 증가 또는 감소 연산자를 사용하여 변수의 값을 변경하는 방법은 더 이상 지원되지 않습니다.

3. 제어문과 반복문

제어문 (Control Statements)
3-1. 조건문 (Conditional Statements):
조건문은 조건에 따라 특정 코드 블록을 실행하거나 실행하지 않도록 하는 데 사용됩니다. 스위프트에서는 주로 if 문과 switch 문을 사용합니다.

// if 문:

let number = 10

if number > 5 {
    print("숫자는 5보다 큽니다.")
} else {
    print("숫자는 5보다 작거나 같습니다.")
}
// switch 문:

let dayOfWeek = "수요일"

switch dayOfWeek {
case "월요일":
    print("첫날입니다.")
case "수요일":
    print("가운데 날입니다.")
default:
    print("다른 요일입니다.")
}

반복문 (Loop Statements):
3-2. 반복문 (Loop Statements):
반복문은 특정 작업을 여러 번 반복하는 데 사용됩니다. 스위프트에서는 for-in 루프, while 루프, repeat-while 루프를 제공합니다.

// for-in 루프:

for i in 1...5 {
    print("숫자: \(i)")
}

for문에는 여러가지 종류가 있습니다.

let names = ["a", "b", "c", "d"]
for x in names[2...] {
    print(x)
}

위의 코드는 배열 names에서 인덱스 2부터 끝까지의 요소를 나타냅니다.

// 범위의 시작과 끝을 지정하여 순회:
let numbers = [1, 2, 3, 4, 5]
for x in numbers[1..<4] {
    print(x)
}

위의 코드는 배열 numbers의 인덱스 1부터 3까지의 요소를 출력합니다.

// 역순으로 배열 순회:
let letters = ["a", "b", "c", "d"]
for x in letters.reversed() {
    print(x)
}

위의 코드는 배열 letters를 역순으로 출력합니다.

// 특정 간격으로 순회:
let numbers = [1, 2, 3, 4, 5]
for x in stride(from: 1, through: 5, by: 2) {
    print(x)
}

위의 코드는 1부터 5까지의 숫자를 2의 간격으로 출력합니다.

// while 루프:

var count = 0

while count < 5 {
    print("카운트: \(count)")
    count += 1
}
// repeat-while 루프:

var number = 1

repeat {
    print("숫자: \(number)")
    number += 1
} while number <= 5

4. 클래스, 객체, 인스턴스의 의미

클래스, 객체, 인스턴스는 객체지향 프로그래밍에서 사용되는 개념입니다.

클래스는 자동차를 만들기 위한 설계도라고 생각할 수 있습니다. 설계도에는 자동차의 크기, 모양, 엔진 등의 정보가 포함되어 있습니다.

객체는 자동차를 실제로 만든 것입니다. 객체는 설계도에서 정의한 정보를 가지고 있으며, 이를 이용하여 동작합니다.

인스턴스는 자동차를 여러 대 만든 것입니다. 각각의 자동차는 설계도에서 정의한 정보를 상속받아 사용할 수 있습니다.

예를 들어, 다음과 같은 클래스가 있다고 가정해봅시다.

class Person {
    var name: String
    var age: Int
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    func sayHello() {
        print("Hello, my name is \(name) and my age is \(age).")
    }
}

위의 클래스는 Person 클래스입니다. 이 클래스는 name과 age라는 속성을 가지고 있으며, sayHello()라는 메서드를 가지고 있습니다.

이 클래스를 이용하여 객체를 생성할 수 있습니다.

let person1 = Person(name: "John", age: 30)
let person2 = Person(name: "Alice", age: 25)

위의 코드는 person1과 person2라는 두 개의 객체를 생성하는 코드입니다. 각각의 객체는 name과 age라는 속성을 가지고 있으며, sayHello()라는 메서드를 사용할 수 있습니다.

객체는 독립적인 존재이기 때문에, 서로 다른 값을 가질 수 있습니다.

person1.name = "John"
person1.age = 30
person2.name = "Alice"
person2.age = 25

위의 코드는 person1과 person2의 name과 age 속성을 각각 "John"과 "Alice"로 변경하는 코드입니다.

객체는 독립적인 존재이기 때문에, 서로 다른 메서드를 호출할 수 있습니다.

person1.sayHello()
person2.sayHello()

위의 코드는 person1과 person2의 sayHello() 메서드를 호출하는 코드입니다. 각각의 객체는 자신의 name과 age 속성을 이용하여 "Hello, my name is John and my age is 30."과 "Hello, my name is Alice and my age is 25."를 출력합니다.

클래스, 객체, 인스턴스는 객체지향 프로그래밍에서 매우 중요한 개념입니다. 이를 이해하고 활용하면 보다 효율적인 프로그래밍을 할 수 있습니다.

5. 타입 세이프티

타입 세이프티(Type Safety)는 프로그래밍 언어에서 데이터의 타입을 엄격하게 관리하는 것을 말합니다.

타입 세이프티를 사용하면 다음과 같은 장점이 있습니다.

(1) 데이터의 안정성: 데이터의 타입을 엄격하게 관리하므로 데이터의 안정성이 보장됩니다.
(2) 런타임 오류 예방: 데이터의 타입을 엄격하게 관리하므로 런타임 오류를 예방할 수 있습니다.
(3) 코드의 가독성: 데이터의 타입을 명확하게 명시하므로 코드의 가독성이 향상됩니다.

func add(a: Int, b: Int) -> Int {
    return a + b
}

let result = add(10, 20)
print(result)

위의 코드는 add() 함수를 이용하여 두 개의 정수를 더한 결과를 반환하는 코드입니다. 이 코드에서는 add() 함수의 입력값과 반환값의 타입이 모두 Int로 명시되어 있으므로, 타입 세이프티가 적용됩니다.

만약 add() 함수의 입력값이나 반환값의 타입이 Int가 아닌 다른 타입으로 변경되면, 이는 타입 불일치(Type Mismatch)가 발생하여 런타임 오류가 발생하게 됩니다.

func add(a: Int, b: Int) -> String {
    return a + b
}

let result = add(10, 20)
print(result)

위의 코드는 add() 함수의 입력값과 반환값의 타입을 Int에서 String으로 변경한 코드입니다. 이 코드에서는 타입 불일치가 발생하여 런타임 오류가 발생하게 됩니다.

타입 세이프티를 사용하면 데이터의 타입을 엄격하게 관리하여 런타임 오류를 예방하고, 코드의 가독성을 향상시킬 수 있습니다

6. 업케스팅, 다운케스팅

업캐스팅은 상속 관계에서 상위 클래스의 객체를 하위 클래스의 객체로 변환하는 것을 말합니다.

예를 들어, 다음과 같은 클래스가 있다고 가정해봅시다.

class Person {
    var name: String
    var age: Int
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

class Student: Person {
    var schoolName: String
    init(name: String, age: Int, schoolName: String) {
        super.init(name: name, age: age)
        self.schoolName = schoolName
    }
}

let student1 = Student(name: "John", age: 20, schoolName: "MIT")
let student2 = Student(name: "Alice", age: 25, schoolName: "Stanford")

let person1 = student1 as Person
let person2 = student2 as Person

위의 코드에서 student1과 student2는 Student 클래스의 객체입니다. 이 객체를 Person 클래스의 객체로 변환하는 것이 업캐스팅입니다.

let person1 = student1 as Person
let person2 = student2 as Person

위의 코드에서 student1과 student2를 Person 클래스의 객체로 변환하는 것이 업캐스팅입니다.

다운캐스팅은 상위 클래스의 객체를 하위 클래스의 객체로 변환하는 것을 말합니다.

예를 들어, 다음과 같은 코드가 있다고 가정해봅시다.

class Person {
    var name: String
    var age: Int
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

class Student: Person {
    var schoolName: String
    init(name: String, age: Int, schoolName: String) {
        super.init(name: name, age: age)
        self.schoolName = schoolName
    }
}

let student1 = Student(name: "John", age: 20, schoolName: "MIT")
let student2 = Student(name: "Alice", age: 25, schoolName: "Stanford")

let person1 = student1 as Person
let person2 = student2 as Person

let student1 = person1 as Student
let student2 = person2 as Student

위의 코드에서 person1과 person2는 Person 클래스의 객체입니다. 이 객체를 Student 클래스의 객체로 변환하는 것이 다운캐스팅입니다.

let student1 = person1 as Student
let student2 = person2 as Student

위의 코드에서 person1과 person2를 Student 클래스의 객체로 변환하는 것이 다운캐스팅입니다.

업캐스팅과 다운캐스팅은 객체지향 프로그래밍에서 매우 중요한 개념입니다. 이를 이해하고 활용하면 보다 효율적인 프로그래밍을 할 수 있습니다.

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

0개의 댓글