본문 바로가기
🍎iOS프로그래밍/겨울방학 특강

Swift문법 - 열거형,구조체

by 둥둥동동# 2022. 1. 6.
728x90

순서

열거형

구조체

구조체와 클래스

 

열거형(enum)

 

관련있는 데이터들의 모음

 

 

Swift의 열거형은 case로 데이터를 정의하고 func 메서드를 가질 수 있습니다

switch문에서 selft키워드로 적절히 분기처리가 필요합니다

enum Week:String {
    case Mon, Tue, Wed, Thur, Fri, Sat, Sun
    
    func printWeek() -> String{
        switch self{
            case .Mon, .Tue, .Wed, .Thur, .Fri:
               return "주중"
            case .Sat, .Sun:
               return "주말"
        }
    }
}
 
print(Week.Sun.printWeek()) //주말
print(Week.Wed.printWeek()) //주중
cs

 

 

 

rawValue

enum Country:String{
  case korea="corea", japan, chian, usa, canada
}
print(Country.korea.rawValue) //corea
print(Country.korea) //korea
print(Country.usa.rawValue)   //usa
print(Country.usa)   //usa
cs
enum Country:String{
    case korea, japan, chian, usa, canada
}
print(type(of:Country.korea.rawValue)) //String
print(type(of:Country.korea)) //Country
print(type(of:Country.usa.rawValue))   //String
print(type(of:Country.usa))   //Country
cs

열거형은 rawValue로 열거형의 자료형으로 지정한 데이터를 출력할 수 있습니다

korea는 corea로 지정하고 rawValue를 출력하니 String형 corea가 출력됩니다

Int형일 경우는 아래와 같습니다

enum Color:Int{
    case blue,pink, yellow=3, red
}
print(Color.blue.rawValue)  // 0
print(Color.pink.rawValue)  // 1
print(Color.yellow.rawValue)// 3
print(Color.red.rawValue)   // 4
cs

물론 이 데이터들의 타입은 모두 Int 입니다

 

 

 

 

연관값 (associated value)

case 하나가 여러개의 값을 가질 수 있습니다

enum Date {
    case intDate(Int,Int,Int)
    case stringDate(String)
}
var todayDate = Date.intDate(2022,02,22)
switch todayDate {
    case .intDate(let year, let month, let day):
        print("\(year)년 \(month)월 \(day)일입니다")
    case .stringDate(let date):
        print(date)
}
cs

각 데이터에 label을 붙일 수 있고 이 경우 생성할 때 명시해야 합니다

 

enum Date {
    case intDate(y:Int,m:Int,d:Int)
    case stringDate(String)
}
var todayDate = Date.intDate(y:2022,m:03,d:22)
switch todayDate {
    case .intDate(let year, let month, let day): //.inDate일 경우
            print("@\(year) \(month) \(day)@")
    case .intDate(y:2022, m:02, d:22):  //2022.02.22일 경우
        print("22년 2월 22일입니다")
    case .intDate(_, m:02, _): //m가 02일 경우
        print("2월입니다 ")
    case .stringDate(let date): //stringDate일 경우
        print(date)
    default:
        print("fail")
}
cs

 

 

 

구조체(struct)

 

구조체 명명법

Swift의 Int, Double, String등 기본 자료형은 구조체입니다 (Array, Dictionary, Set은 Generic Struct, nil도 구조체)

구조체를 정의하는 것은 새로운 타입을 생성하는 것과 마찬가지 입니다

대문자 카멜케이스를 활용하여 명명합니다

 

구조체 인스턴스 생성과 초기화

아래에 구조체는 Man이란 이름을 갖고 멤버 프로퍼티로 age과 name를 갖습니다

struct Man{
    var age:Int
    var name:String
}
cs

 

Man의 인스턴스를 생성하고 초기화 할 땐 memberwise initializer를 사용합니다

구조체에서 정의하지 않았지만 자동으로 생성자가 만들어 집니다

var로 선언된 구조체는 프로퍼티는 수정이 가능하고 let는 수정이 불가능합니다

var Kim:Man = Man(age:20, name:"John")
print(Kim) //Man(age:20,name:"John")
Kim.age = 31
Kim.name = "Smith"
print(Kim) //Man(age:31,name:"Smith")
 
let Park:Man = Man(age:20,name:"George")
Park.age = 10  //에러발생
cs

 

 

상속 불가

구조체,enum은 값타입

 

 

구조체와 클래스

 

구조체와 클래스의 공통점

  • stored프로퍼티 선언
  • 메소드 정의
  • 첨자( . )로 값 접근
  • 생성자로 값 초기화
  • extention으로 확장가능
  • protocol 채택 가능

 

구조체와 클래스의 차이점

  • 클래스는 상속이 가능
  • 클래스의 인스턴스는 타입캐스팅(as, is)이 가능합니다
  • 클래스의 인스턴스는 deinit()로 자원을 반환할 수 있습니다
  • 클래스는 참조횟수 계산(Reference Couting)을 통해 여러곳에서 참조 가능

 

구조체는 값타입(Value Type), 클래스는 참조타입(Reference Type)

스위프트의 기본타입(Int, Float, Stirng, Double,,,)은 모두 구조체로 정의되었습니다

즉 기본자료형들은 모두 값타입을 의미하는데 인자로 값을 전달할 때 값만 전달되어 기존값을 아무리 수정해도 새로 전달받은 값은 영향을 받지 않습니다

 

반면 클래스는 참조타입으로 값을 전달할 때 주소를 참조값(주소)를 전달합니다 따라서 기존값을 변경하면 새로 전달받은 값은 영향을 받게 됩니다

 

비교를 위해 클래스와 구조체를 선언했습니다 

구조체는 memberwise initializer가 자동으로 만들어져 초기값이나 init()메서드를 정의하지 않아도 됩니다

메서드에서 값을 수정하고자 할 경우 mutatig키워드를 추가해야 합니다

struct ManStruct {
    var age:Int
    var name:String
}
class ManClass {
    var age:Int
    var name:String
    init (age:Int,name:String){
        self.age = age
        self.name = name
    }
}
cs

 

구조체

Park 변수에 Kim을 할당하고 Kim의 멤버프로퍼티를 수정했습니다

하지만 Park에는 아무런 영향을 주지 못했습니다

클래스

Choi변수에 Lee를 할당하고 Choi의 age 프로퍼티를 수정하니 Lee의 결과값이 영향을 받았습니다

var Kim:ManStruct = ManStruct(age:20,name:"John")
var Park = Kim
print(Kim) //ManStruct(age:20,name:"John")
Kim.age = 31
Kim.name = "Smith"
print(Kim)  //ManStruct(age:31,name:"Smith")
print(Park) //ManStruct(age:20,name:"John")
 
 
var Lee:ManClass = ManClass(age:10,name:"John")
var Choi = Lee
print("age:\(Lee.age) name:\(Lee.name)"//ManClass(age:10,name:"John")
print("age:\(Choi.age) name:\(Choi.name)")//ManClass(age:10,name:"John")
Choi.age = 22
print("age:\(Lee.age) name:\(Lee.name)"//ManClass(age:22,name:"John")
print("age:\(Choi.age) name:\(Choi.name)")//ManClass(age:22,name:"John")
cs

 

위와 같은 결과가 나온 이유는 변수가 클래스의 인스턴스 주소값을 저장하기 때문입니다

 

Choi와 Lee가 같은 곳을 가리키고 있으니 Choi의 프로퍼티를 수정하면 Lee의 프로퍼티가 수정된것과 같습니다

 

구조체는 언제 쓸까?

애플 공식문서는 아래의 가이드라인을 제시했습니다

  • 간단한 값들을 묶어 사용할 경우
  • 값을 복사해도 좋은 경우
  • 멀티쓰레드 환경일 경우
  • 상속이 필요하지 않은 경우(3차원 좌표시스템, 순열 등)

 

 

 

 

참고자료

 

한성현 교수님의 유튜브강의

https://www.youtube.com/channel/UCM8wseo6DkA-D7yGlCrcrwA

 

 

 

728x90

댓글