데이터 타입 고급

Gooreum·2021년 10월 28일
0

Swift

목록 보기
3/16

데이터 타입 안심

  • 스위프트에서 값 타입의 데이터 교환은 엄밀히 말하면 타입캐스팅이 아닌 새로운 인스턴스를 생성하여 할당하는 것.

데이터 타입 안심이란

  • 스위프트는 컴파일 시 타입을 확인해하는데, 이것을 '타입 확인'이라 한다.

타입 추론

  • 스위프트에서는 변수나 상수를 선언할 때 특정 타입을 명시하지 않더라도 컴파일러가 할당된 값을 기준으로 변수나 상수의 타입을 결정한다.

타입 별칭

  • 스위프트에서 기본으로 제공하는 데이터 타입이든, 사용자가 임의로 만든 데이터 타입이든 이미 존재하는 데이터 타입에 임의로 다른 이름(별칭)을 부여할 수 있음. 그런 다음 기본 타입 이름과 이후에 추가한 별칭을 모두 사용할 수 있음.
    typealias MyInt = Int
    typealias YourInt = Int
    typealias MyDouble = Double
    
    let age: MyInt = 100   //MyInt는 Int의 또 다른 이름.
    let year: YourInt = 2080   //YourInt도 Int의 또 다른 이름
    
    //MyInt도 YourInt도 Int이기 때문에 같은 타입으로 취급한다.
    year = age

튜플(Tuple)

  • 튜플은 타입의 이름이 따로 지정되어 있지 않은, 프로그래머 마음대로 만드는 타입이다. '저장된 데이터의 묶음'이라고 표현할 수 있음.
  • 튜플은 타입 이름이 따로 없으므로 일정 타입의 나열만으로 튜플 타입을 생성해줄 수 있음. 튜플에 포함될 데이터의 개수는 자유롭게 정할 수 있음.
    //String, Int, Double 타입을 갖는 튜플
    var person: (String, Int, Double) = ("Yagom", 100, 182.5)
    
    //인덱스를 통해서 값을 빼올 수 있다.
    print("이름:\(person.0), 나이: \(person.1), 신장: \(person.2)")
    
    person.1 = 99 //인덱스를 통해 값을 할당할 수 있다.
    person.2 = 178.5
    print("이름:\(person.0), 나이: \(person.1), 신장: \(person.2)")
  • 그러나 인덱스만으로 각 요소의 데이터가 무엇을 나타내는지 쉽게 파악하기 어렵기 때문에 튜플의 요소마다 이름을 붙여줄 수 있다.
    //String, Int, Double 타입을 갖는 튜플
    var person: (name: String, age: Int, height: Double) = ("Yagom", 100, 182.5)
    
    //인덱스를 통해서 값을 빼올 수 있다.
    print("이름:\(person.name), 나이: \(person.age), 신장: \(person.height)")
    
    person.1 = 99 //인덱스를 통해 값을 할당할 수 있다.
    person.2 = 178.5
    print("이름:\(person.0), 나이: \(person.1), 신장: \(person.2)")
    
    (4) 튜플 별칭을 지정해줄 수 있다.
    //String, Int, Double 타입을 갖는 튜플
    typealias PersonTuple = (name: String, age: Int, height: Double)
    let yagom: PersonTuple = ("yagom", 100, 178.5)
    let eric: PersonTuple = ("Eric", 150, 183.5)

컬렉션형

  • 스위프트는 튜플 외에도 많은 수의 데이터를 묶어서 저장하고 관리할 수 있는 컬렉션 타입을 제공한다. 컬렉션 타입에는 배열(array), 딕셔너리(dictionary), 세트(set) 등이 있다.

배열

  • 배열은 같은 타입의 데이터를 일렬로 나열한 후 순서대로 저장하는 형태의 컬렉션 타입이다.
  • 스위프트의 Array는 C 언어의 배열처럼 버퍼(buffer)이다. 단, C 언어처럼 한 번 선언하면 크기가 고정되던 버퍼가 아니라, 필요에 따라 자동으로 버퍼의 크기를 조절해주므로 요소의 삽입 및 삭제가 자유롭다. 스위프트는 이런 리스트 타입을 Array, 즉 배열이라 표현한다.

딕셔너리

  • 딕셔너리는 요소들이 순서 없이 키와 값의 쌍으로 구성되는 컬렉션 타입이다. 딕셔너리에 저장되는 값은 항상 키와 쌍을 이루게 되는데, 딕셔너리 안에는 키가 하나이거나 여러 개일 수 있다. 단, 하나의 딕셔너리 안의 키는 같은 이름을 중복해서 사용할 수 없다.
  • 딕셔너리는 Dictionary라는 키워드와 키의 타입과 값의 타입 이름의 조합으로 써준다. 대괄호로 키와 값의 타입 이름의 쌍을 묶어 딕셔너리 타입임을 표현한다.
  • *딕셔너리의 선언과 생성
    //typealias를 통해 조금 더 단순하게 표현해볼 수도 있다.
    typealias StringIntDictionary = [String: Int]
    //키는 String, 값은 Int 타입인 빈 딕셔너리를 생성한다.
    var numberForName: Dictionary<String, Int> = Dictionary<String, Int>()
    //위 선언과 같은 표현, [String, Int] 는 Dictionary<String, Int>의 축약 표현이다.
    var numberForName: [String, Int] = [String, Int]()
    //위 코드와 같은 동작을 한다.
    var numberForName: StringIntDictionary = StringIntDictionary()
    //딕셔너리의 키와 값 타입을 정확히 명시해줬다면 [:] 만으로도 빈 딕셔너리를 생성할 수 있다.
    var numberForName: [String: Int] = [:]
    //초깃값을 주어 생성해줄 수도 있다.
    var numberForName: [String: Int] = ["yagom": 100, "chulsoo": 200, "jenny": 300]
  • 딕셔너리는 각 값에 키로 접근할 수 있다. 딕셔너리 내부에서 키는 유일해야 하며, 값은 유일하지 않다. 딕셔너리는 배열과 다르게 딕셔너리 내부에 없는 키로 접근해도 오류가 발생하지 않는다. 다만 nil을 반환하게 된다. 특정 키에 해당하는 값을 제거하려면 removeValue(forKey:) 메서드를 사용한다. 키에 해당하는 값이 제거된 후 반환된다.

세트

  • 세트는 같은 타입의 데이터를 순서 없이 하나의 묶음으로 저장하는 형태의 컬렉션 타입이다. 세트 내의 값은 모두 유일한 값, 즉 중복된 값이 존재하지 않는다. 그래서 세트는 보통 순서가 중요하지 않거나 각 요소가 유일한 값이어야 하는 경우에 사용한다. 또, 세트의 요소로는 해시 가능한 값이 들어와야 한다. *스위프트 표준 라이브러리의 Hashable 프로토콜을 따른다는 것을 의미한다. 스위프트의 기본 데이터 타입은 모두 해시 가능한 값이다.
  • 세트는 Set 키워드와 타입 이름의 조합으로 써준다. 또, 배열과 마찬가지로 대괄호로 값들을 묶어 세트 타입임을 표현한다. 배열과 달리 줄여서 표현할 수 있는 축약형(예를 들어 Array 를 [Int]로 축약해 쓸수 있던)이 없다.
  • 세트는 자신 내부의 값들이 모두 유일함을 보장하므로, 집합관계를 표현하고자 할 때 유용하게 쓰일 수 있으며, 두 세트의 교집합, 합집합 등을 연산하기에 매우 용이하다. 또한 sorted() 메서드를 통하여 정렬된 배열을 반환해줄 수도 있다.
    // [1]집합연산!!
    let englishClassStudents: Set<String> = ["john", "chulsoo", "yagom"]
    let koreanClassStudents: Set<String> = ["jenny", "yagom", "chulsoo", "hana", "minsoo"]
    
    //교집합 : yagom, chulsoo
    let intersectSet: Set<String> = englishClassStudents.intersection(koreanClassStudents)
    //여집합의 합(배타적 논리합) : john, jenny, hana, minsoo
    let symmetricDiffSet: Set<String> = englishClassStudents.symmetricDifference(koreanClassStudents)
    //합집합 : minsoo, jenny, john, yagom, chulsoo, hana
    let unionSet: Set<String> = englishClassStudents.union(koreanClassStudents)
    //차집합 : john
    let subtractSet: Set<String> = englishClassStudents.subtracting(koreanClassStudents)
    
    //[2] 포함관계 연산
    let: Set<String> = ["비둘기", "닭", "기러기"]
    let 포유류: Set<String> = ["사자", "호랑이", "곰"]
    let 동물:.union(포유류) //새와 포유류의 합집합
    print(.isDisjoint(with: 포유류))   //서로 배타적인지 - true
    print(.isSubset(of: 동물))        //새가 동물의 부분집합인가요? - true
    print(동물.isSuperset(of: 포유류))   //동물은 포유류의 전체집합인가요? - true
    print(동물.isSuperset(of:))      //동물은 새의 전체집합인가요? - true

열거형

  • 열거형은 연관된 항목들을 묶어서 표현할 수 있는 타입이다.
  • 열거형은 배열이나 딕셔너리 같은 타입과 다르게 프로그래머가 정의해준 항목 값 외에는 추가/수정이 불가하다. 따라서 딱 정해진 값만 열거형 값에 속할 수 있다.
  • 열거형은 아래 경우 요긴하게 사용가능하다.
    • 제한된 선택지를 주고 싶을 때
    • 정해진 값 외에는 입력받고 싶지 않을 때
    • 예상된 입력 값이 한정되어 있을 때
  • 스위프트의 열거형은 항목별로 값을 가질 수도, 가지지 않을 수도 있다.
  • 열거형 각 항목이 원시 값(raw value)이라는 형태로 (정수, 실수, 문자 타입 등의) 실제 값을 가질 수도 있다. 또는 연관 값(associated values)을 사용하여 다른 언어에서 공용체라고 불리는 값의 묶음도 구현할 수 있다.
  • 열거형은 switch 구문과 만났을 때 멋지게 활용해볼 수 있다.

기본 열거형

  • 스위프트의 열거형은 enum이라는 키워드로 선언할 수 있다.
profile
하루하루 꾸준히

0개의 댓글