A Swift Tour로 Swift 공부하기 #6. Enumerations and Structures

minin·2021년 2월 12일
1

A Swift Tour

목록 보기
5/8

🍫 notion으로 보기
*본 포스트는 애플의 'A Swift Tour'를 바탕으로 작성되었으며, 공부하며 기록용으로 작성한 포스트이기 때문에 정확하지 않은 정보가 있을 수 있습니다!
** notion으로 작성한 문서를 임시로 올려둔 포스트이기 때문에 사진 링크의 오류와 문서의 형식 등으로 인해 보시기에 불편함이 있을 수 있습니다. (사진이 안나오거나 코드를 보기 불편한 점 등은 빠른 시일 내에 수정하도록 하겠습니다!)

6. Enumerations and Structures

1. enum

열거형enumeration을 만들기 위해서 enum을 사용한다. 클래스와 다른 이름이 붙여진 타입들과 같이, 열거체들은 그들과 함께 메소드를 만들 수 있다.

enum Rank: Int {
    case ace = 1
    case two, three, four, five, six, seven, eight, nine, ten
    case jack, queen, king

    func simpleDescription() -> String {
        switch self {
        case .ace:
            return "ace"
        case .jack:
            return "jack"
        case .queen:
            return "queen"
        case .king:
            return "king"
        default:
            return String(self.rawValue)
        }
    }
}
let ace = Rank.ace
let aceRawValue = ace.rawValue

***self**

swift에서의 self는 인스턴스의 특별한 속성property이다. 그 스스로의 인스턴스를 잡아놓는. 대부분의 self생성자initializer 혹은 클래스의 메소드, 구조체 혹은 열거형에서 나타난다.

experiment

두개의 Rank 값의 rawValue를 비교하는 함수를 작성하라.

func compareRank(valA: Rank, valB: Rank) -> Bool {
    return valA.rawValue == valB.rawValue
}

compareRank(valA: Rank.ace, valB: Rank.queen)  //  false
compareRank(valA: Rank.two, valB: Rank.two)  //  true

기본적으로 스위프트는 raw 값에 0에서 시작해 1씩 증가하도록 할당하고 있다. 그러나 이는 값을 명시적으로 지정하는 것을 통해 바꿀 수 있다. 위의 예시에서, ace는 명시적으로 1이라는 raw값을 받았고, 남은 raw 값들은 그 다음 순서대로 할당받는다. 그리고 String이나 열거체의 raw 타입으로써의 floating-point number도 사용 가능하다floating-point numbers as the raw type of an enumeration. rawValue 속성을 이용해 열거체 케이스의 raw 값에 접근할 수 있다.

init?(rawValue:)

raw 값으로부터 열거체의 인스턴스를 만들기 위해 init?(rawValue:) 생성자를 사용한다. init?(rawValue:)는 열거체 케이스에 매치되는 raw 값을 반환하거나, 만약 매칭되는 Rank가 없으면 nil을 반환한다.

if let convertedRank = Rank(rawValue: 3) {  // rawValue가 3인 값을 매칭 => "three"
	//  return String(self.rawValue) => convertedRank.rawValue => "3" (: String)
	let threeDescription = convertedRank.simpleDescription()
}

⚠️ Initialization of immutable value 'threeDescription' was never used; consider replacing with assignment to '_' or removing it.

//위의 코드를 수정한 것 (threeDescrption을 사용하지 않아서)
if let convertedRank = Rank(rawValue: 3) {
		_ = convertedRank.simpleDescripton()
}

열거체의 케이스 값들은 진짜actual 값들이며, 단지 그들의 다른 표현법이 아니다. 실제로, 케이스 내에서 의미 있는 raw값이 아니라면 제공할 필요가 없다.

enum ***Suit*** {  //  열거체
    case spades, hearts, diamonds, clubs

    func simpleDescription() -> String {
        switch self {
            case .spades:
                return "spades"
            case .hearts:
                return "hearts"
            case .diamonds:
                return "diamonds"
            case .clubs:
                return "clubs"
         }
    }
}
let hearts = Suit.hearts  //hearts
let heartsDescription = hearts.simpleDescription()  //  "hearts"

hearts 의 두 가지의 방법

  1. 값을 상수 hearts에 할당할 때, 명확한 타입이 명시되어 있지 않기 때문에 열거체 케이스 Suit.hearts가 full name으로써 참조된다.
  2. switch문 안에서, 열거체 케이스는 함축된 형태인 .heart로부터 참조된다. 이는 self의 값이 suit인 것을 알기 때문이다. 즉 만약 값의 타입을 이미 알고 있다면 언제든지 함축형을 쓸 수 있다.

**experiment**

spades와 clubs에 "black"을 리턴하고, hearts와 diamonds에 "red"를 리턴하는 color() 메소드를 Suit에 추가하라.

enum Suit {
	case hearts, clubs, spades, diamonds
	func color() -> String {
	        switch self {
	        case .spades, .clubs:
	            return "black"
	        case .hearts, .diamonds:
	            return "red"
	        }
	    }
}

let heartsColor = Suit.hearts.color()  //"red"
let spadesColor = Suit.spades.color()  // "black"

associated values

  1. 만약 열거형이 raw값을 가지고 있으면, 이 값들은 선언하는 부분에서 결정되는데, 이는 특정한 열거체 케이스의 모든 인스턴스들은 같은 raw 값을 가진다는 것을 의미한다.
  2. 또는 값들이 인스턴스가 만들어질 때 관련된 값associated을 가지게 하는 것인데, 이들은 열거체 케이스의 각 인스턴스와 다를 수 있다. 당신은 관련된 값associated values을 열거체 케이스 인스턴스의 속성들properties을 저장하는 것으로 생각할 수 있다. 예를 들어, 서버로부터 일출과 일몰의 시간을 요청하는 케이스를 생각해보자. 서버는 요청받은 정보에 대해서 응답하거나, 무엇이 잘못된 것에 대해 응답한다.
//일출과 일몰의 시간을 요청하는 서버

enum ServerResponse {
    case result(String, String)
    case failure(String)
}

let success = ServerResponse.result("6:00 am", "8:09 pm")
let failure = ServerResponse.failure("Out of cheese.")

//success이기 때문에 success문 출력
switch success {
case let .result(sunrise, sunset):
    print("Sunrise is at \(sunrise) and sunset is at \(sunset).")
case let .failure(message):
    print("Failure... \(message)")
}

❗️sunrisem, sunset 시간이 ServerResponse 값으로부터 추출되었다.

: switch case와 값이 매칭되었기 때문에

***case let: 뒤따르는 연관된 값들을 단지 variable name으로 묶는 줄임말 ?. 그러나 각각의 variable name 앞에 let을 적어줄 수도 있다. 출처**

**experiment**

ServerResponse와 switch문에 세번째 case값을 추가하라.

enum ServerResponse {
	case missing(String)
}

let missing = ServerResponse.missing("Cannot find the data.")

switch success {
	case let .missing(missingMessage):
print("Server can't find that information.")
}

**struct**

구조체structure를 만들기 위해 struct를 사용한다. 구조체는 메소드와 생성자를 포함하여 클래스와 같은 많은 역할을 지원한다. 구조체와 클래스의 가장 중요한 다른 점은 구조체는 전달될 때 언제나 복사되는 반면 클래스는 참조로 전달된다.

struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
}

let threeOfSpades = Card(rank: .three, suit: .spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
profile
🍫 iOS 🍫 Swift

0개의 댓글