[Swift] 데이터 타입 - 2

김태형·2023년 3월 19일
0

Swift

목록 보기
6/22



데이터 타입 안심

  • 스위프트는 다른 타입끼리의 데이터 교환은 꼭! 타입캐스팅을 거쳐야 한다!
    --> 데이터 타입 간의 자료 교환이 까다로움

  • 하지만 까다롭기 때문에 데이터 타입을 안심하고 사용할 수 있음


타입 추론

  • 특정 타입을 명시하지 않아도 (값의 타입이 명확하다면) 컴파일러가 타입을 결정해줄 수 있음
  • 하지만 타입이 지정된 후에는 다른 타입을 할당할 수 없음
var name = "Ted"    //타입을 지정하지 않았으나, 타입 추론으로 인해 String 타입으로 선언
name = 100    //String 타입으로 지정되었기 때문에 오류 발생

타입 별칭 (typealias)

  • 이미 존재하는 데이터 타입에 임의로 다른 이름(별칭)을 부여할 수 있음
  • &를 통해 여러 가지를 묶을 수도 있음
  • 모든 타입을 typealias로 지정할 수 있음 (클로저, 클래스 안에 있는 enum 등)
protocol Naming {
    func getName() -> String
}

protocol Aging {
    func getAge() -> Int
}

typealias Friendable = Naming & Aging   // Naming과 Aging을 합친 것을 Friendable로 부르겠다

typealias FummNaming = Naming   //하나만 설정해줘도 됨

struct Friend25: Friendable {    //Friend25: Naming & Aging 으로 쓴 것과 같은 것임

    var name: String
    var age: Int
    
    func getName() -> String {
        return self.name
    }
    
    func getAge() -> Int {
        return self.age
    }
    
}


typealias StringBlock = (String) -> Void

func sayHi(completion: StringBlock) {   //completion: (String) -> Void 와 같은 것
    print("안녕하세요?")
    completion("테드입니다")
}

sayHi(completion: { saying in
    print("여기서 받음 : ", saying)
})


컬렉션 타입

배열, 딕셔너리, 세트



배열 (Array)

  • 순서가 있는 컬렉션 타입

딕셔너리 (Dictionary)

  • 순서 없이 키(key)와 값(value)의 쌍으로 이루어진 컬렉션
  • 키는 중복해서 사용할 수 없음
  • 내부에 없는 키로 접근한다면 에러가 아니라 nil이 반환됨

세트 (Set)

  • 순서가 없고, 멤버가 유일한 컬렉션 (수학에서의 집합)
  • 교집합, 합집합, 차집합 등 표현 가능

//빈 Int Array 생성
var integers: Array<Int> = Array<Int>()   //[]로 생성해도 됨
integers.append(1)   //[1]
integers.append(100)   //[1, 100]

integers.append(101.1)   //에러

integers.contains(100)   //true
integers.contains(99)   //false

integers.remove(at: 0)  //Array 안에 특정 인덱스 안의 부분을 삭제
integers.removeLast()  //Array 안에 마지막 인덱스 삭제
integers.removeAll()    //Array 안에 모든 인덱스 삭제

integers.count   //인덱스 안의 값 개수


//Array<Double>과 [Double]은 같은 표현 !
//빈 Double Array 생성
var doubles: Array<Double> = [Double]()

//빈 String Array 생성
var strings: [String] = [String]()

//빈 character Array 생성
var characters: [Character] = [] //이렇게도 가능함


//let을 선언하여 Array를 선언하면 불변 Array 
let immutableArray = [1, 2, 3]


//let array는 remove, append 등 사용 불가



var anyDictionary: Dictionary<String, Any> = [String: Any]()
anyDictionary["someKey"] = "value"
anyDictionary["anotherkey"] = 100 

anyDictionary.removeValue(forKey, "anotherKey")  //anotherKey라는 키값과 value값 없앰
anyDictionary["someKey"] = nil   //someKey 키값 삭제

let emptyDictionary: [String: String] = [:]
let initialzedDictionary: [String: String] = ["name" : "yagom", "gender" : "male"]   //let을 선언했기 때문에, 값의 변경은 불가능함


let someValue: String = initializedDictionary["name"]  //에러 발생. 딕셔너리의 key에 해당하는 값이 없을 수도 있는 불확실성 때문에 없음




//빈 Int Set 생성
var integerSet: Set<Int> = Set<Int>()
integerSet.insert(1)  //(inserted true, memberAfterInsert 1)
intergerSet.insert(100)   //(inserted true, memberAfterInsert 100)

intergerSet.insert(99)    //(inserted true, memberAfterInsert 99)
intergerSet.insert(99)    //(inserted false, memberAfterInsert 100)
intergerSet.insert(99)    //(inserted false, memberAfterInsert 100)



let setA: Set<Int> = [1, 2, 3, 4, 5]   //{5, 2, 3, 1, 4)
let setB: Set<Int> = [3, 4, 5, 6, 7]

let union: Set<Int> = setA.union(setB)   //합집합   {2, 4, 5, 6, 7, 3, 1}

let sortUnion: [Int] = union.sorted()
let intersction: Set<Int> = setA.intersection(setB)    //교집합   {5, 3, 4}
let subtracting: Set<Int> = setA.subtracking(setB)   //차집합    {2,1} 

기타

튜플

  • 지정된 데이터의 묶음
  • 타입의 이름이 따로 지정되어 있지는 않음
  • 파이썬의 튜플과 비슷
var person: (String, Int, Double) = ("Ted", 26, 177)
//person.1 등으로 값을 빼 올 수 있음

인덱스만으로는 데이터의 의미 유추가 힘들기 때문에 이름을 붙여줄 수 있음

var person: (name: String, age: Int, height: Double) = ("Ted", 26, 177)
//person.name 등으로 값을 빼올 수 있음

튜플을 선언할 때마다 계속 써주면 불편함 --> 타입 별칭을 사용하여 깔끔하게 작성 가능

typealias PersonTuple = (name: String, age: Int, height: Double)
let ted: PeronsTuple = ("Ted", 26, 177)
//계속 (name: String, age: Int, height: Double)를 선언할 필요가 없어짐

열거형 (enum)

  • 각각의 케이스가 고유의 값으로 취급됨
  • 메서드도 추가 가능
  • 다른 열거형의 시각으로 보지 말기
  • rawValue(원시값)를 통해 case에 대한 값을 가질 수 있음
  • 열거형의 Int값은 값을 지정하지 않으면 자동으로 1씩 증가함
  • rawValue를 통해 초기화 한 인스턴스는 옵셔널 타입임
  • 열거형에 메서드도 추가 가능
//열거형

enum Weekday {
	case mon
	case tue
	case wed
	case thu, fri, sat, sun   //그냥 한번에 ,로 묶어도 상관없음
}

var day = Weekday.mon
day = .tue

switch day {
	case .mon, .tue, .wed, .thu:
		print("평일입니다")
	case Weekday.fri:
		print("금요일")
	case .sat, .sun:
		print("신나는 주말!")
}


//정수값을 가질 수 있음
//만약 정수값을 정의하고 뒤에 정의하지 않는다면, +1 증가하여 저장됨

enum Fruit: Int {
    case apple = 0
    case grape = 3
    case peach    //4 (grape가 3인데, peach는 정의가 되어있지 않아 자동으로 1이 증가)
    case orange
}




enum School: String {
	case elementary = "초등"
	case middle = "중등"
	case high = "고등"
	case university
}

print(\(School.university.rawValue))  //university : case의 이름을 그대로 가져옴

let apple: Fruit? = Fruit(rawValue: 0)   //옵셔널이 아니면 에러

if let orange: Fruit = Fruit(rawValue: 5) {
	print("rawValue 5에 해당하는 케이스는 \(orange)입니다")
} else {
		print("rawValue 5에 해당하는 케이스가 없습니다")
}




//메서드 추가 가능

enum Month {
	case dec, jan, feb
	case mar, apr, may
	case jun, jul, aug
	case sep, oct, nov

	func printMessage() {    //메서드
		switch self {    //enum Month안에 func가 있기 때문에 self == Month가 된다
			case .mar, .apr, .may:
				print("봄")
			case .jun, .jul, .aug:
				print("여름")
			case .sep, .oct, .nov:
				print("가을")
			case .dec, .jan, .feb:
				print("겨울")
			}
	}
}

Month.mar.printMessage()

연관값

  • 열거형 내의 항목(case)이 자신과 연관된 값을 가질 수 있음
  • 모든 항목(case)이 연관 값을 가질 필요는 없음
enum MainDish {
	case pasta(taste: String)
	case pizza(dough: String, topping: String)
	case rice
}

var dinner: MainDish = MainDish.pasta(taste: "크림")    //크림 파스타
dinner = .pizza(dough: "치즈 크러스트", topping: "불고기")    //불고기 치즈 크러스트 피자

[출처] 스위프트 프로그래밍 (야곰), 야곰의 스위프트 기초문법 강좌, 개발하는 정대리 스위프트 강좌

0개의 댓글