본문 바로가기
iOS/Swift

Swift-3. 구조체, 열거형

by 헤콩 2023. 2. 24.
반응형

** edwith - Swift 프로그래밍 입문 강의 참고 **

 

 

# 구조체 #

- swift 대부분 타입은 구조체로 되어 있습니다.

- 구조체는 값(value) 타입

- 타입이름은 대문자 카멜케이스를 사용하여 정의

// 구조체 기본 문법
struct /*이름*/ {
    /* 구현부분 */
}
// 구조체 property 및 method 구현
struct Sample {
    // 가변 프로퍼티 : 값 변경 가능
    var mutableProperty: Int = 100
    
    // 불변 프로퍼티 : 값 변경 불가능
    let immutableProperty: Int = 100
    
    // 타입 프로퍼티 : static 키워드 사용 - 타입 자체가 사용하는 프로퍼티
    static var typeProperty:Int = 100
    
    // 인스턴스 메서드 : 인스턴스가 사용하는 메서드
    func instanceMethod() {
    	print("instance method")
    }
    
    // 타입 메서드 : static 키워드 사용 - 타입 자체가 사용하는 메서드
    static func typeMethod() {
    	print("type method")
    }
}
// 구조체 사용
var mutable: Sample = Sample() // 가변 인스턴스 생성
mutable.mutableProperty = 200
mutable.immutableProperty = 200 // 컴파일 오류 - 불변 프로퍼티이기 때문

let immutable: Sample = Sample() // 불변 인스턴스 생성
immutable.mutableProperty = 200 // 컴파일 오류 - 불변 인스턴스이기 때문, 만약 immutable이 구조체가 아닌 클래스였다면 200으로 변경 가능.
immutable.immutableProperty = 200 // 컴파일 오류

// 타입 프로퍼티 및 메서드
Sample.typeProperty = 300
Sample.typeMethod() // type method

// 인스턴스에서는 타입 프로퍼티나 타입 메서드를 사용할 수 없습니다.
mutable.typeProperty = 400 // 컴파일 오류
mutable.typeMethod() // 컴파일 오류

 

예시) 학생 구조체 만들어보기

struct Student {
    var name: String = "unknown"
    var 'class': String = "튤립"	// 키워드도 '로 묶어주면 이름으로 사용 가능
    
    // 타입 메서드
    static func selfIntroduce() {
    	print("학생 타입 메서드입니다.")
    }
    
    // 인스턴스 메서드
    func selfIntroduce() {
    	print("저는 \(self.class)반 \(name)입니다.")
    }
}

Student.selfIntroduce()	// 학생 타입 메서드입니다.

var myStudent: Student = Student()
myStudent.name = "빈빈"
myStudent.class = "장미"
myStudent.selfIntroduce()	// 저는 장미반 빈빈입니다.

let yourStudent: Student = Student()
yourStudent.name = "지지"	// 컴파일 오류 - Student가 구조체가 아닌 클래스였다면 가능.
yourStudent.selfIntroduce()	// 저는 튤립반 unknown입니다.

 

# 열거형 #

- 타입이 명확할 경우, 열거형의 이름을 생략할 수 있습니다.

- switch 구문에서 사용하면 좋습니다.

// 열거형 사용
enum WeekDay {
    case mon
    case tue
    case wed
    case thu, fri, sat, sun
    
    func printMessage() { // Swift의 열거형에는 메서드도 추가 가능
    	switch self {
        	case mon, tue, wed
            	print("월화수")
            case thu, fri, sat, sun
            	print("목금토일")
        }
    }
}

var day: Weekday = Weekday.mon
day = .tue // 타입이 명확하기 때문에 이렇게 표현해도 가능.
print(day)	// tue
WeekDay.tue.printMessage()	// 월화수

 

rawValue (원시값)

- C언어의 enum처럼 정수값을 가질 수 있습니다.

- rawValue는 case별로 각각 다른 값을 가져야 합니다. (자동으로 1일 증가된 값이 할당)

- rawValue를 반드시 지닐 필요가 없다면 굳이 만들지 않아도 됨

enum Fruit: Int {
    case apple = 0
    case grape = 1
    case peach
    case mango = 0	// 오류 - apple과 원시값이 같아서. 같은 원시값이 있으면 안됨.
}

print(Fruit.peach.rawValue)	// 2



// 정수 타입 뿐만 아니라, Hashable 프로토콜을 따르는 모든 타입을 원시값의 타입으로 지정할 수 있습니다.
enum School: String {
    case elementary = "초등"
    case middle = "중등"
    case high = "고등"
    case university
}

print(School.middle.rawValue)	// 중등
print(School.university.rawValue)	// university
// 열거형의 원시값 타입이 String일 때, 원시값이 지정되지 않았다면 case의 이름을 원시값으로 사용합니다.

 

원시값을 통한 초기화

- rawValue를 통해 초기화 할 수 있습니다.

- rawValue가 case에 해당하지 않을 수 있으므로, rawValue를 통해 초기화 한 인스턴스는 옵셔널 타입입니다.

// rawValue를 통해 초기화 한 열거형 값은 옵셔널 타입이므로 Fruit 타입이 아닌 Fruit? 타입.
let apple: Fruit? = Fruit(rawValue: 0)

// if-let 구문을 사용하면 rawValue에 해당하는 케이스를 곧바로 사용할 수 있습니다.
if let orange: Fruit = Fruit(rawValue: 5) {
    print("rawValue 5에 해당하는 케이스는 \(orange)입니다.")
} else {
    print("rawValue 5에 해당하는 케이스가 없습니다.")
}
// rawValue 5에 해당하는 케이스가 없습니다.

 

# Value Type(값 타입)과 Reference Type(참조 타입) 비교#

- Value Type(값 타입)

     + 열거형, 구조체

     + 상속 불가능

     + 데이터를 전달할 때 값을 복사하여 전달

- Reference Type(참조 타입)

     + 클래스

     + 상속 가능

     + 데이터를 전달할 때 값의 메모리 위치를 전달

struct ValueType {
    var property = 1
}

class ReferenceType {
    var property = 1
}

// 1. ValueType
let firstStructInstance = ValueType()
var secondStructInstance = firstStructInstance
secondStructInstance.property = 2

print(firstStructInstance)	// 1
print(secondStructInstance)	// 2

// 2. ReferenceType
let firstClassReference = ReferenceType()
let secondClassReference = firstClassReference
secondClassReference.property = 2

print(firstClassReference.property)	// 2
print(secondClassReference.property)	// 2
반응형

댓글