* 이 글은 "스위프트 프로그래밍 (3판)" 및 야곰닷넷의 "스위프트 기초 강의", The Swift Programming (번역본)을 공부하며 정리한 내용입니다.
사용자 정의 타입은, 프로그래머가 데이터를 용도에 맞게 묶어 표현하고자 할 때 유용하게 쓰입니다. 구조체와 클래스는 프로퍼티와 메소드를 사용하여 구조화된 데이터 및 기능을 가질 수 있습니다. Swift에서 이 둘은 문법상 생김새는 비슷하나, 구조체는 값 타입, 클래스는 참조 타입이라는 것이 가장 큰 차이라고 할 수 있습니다. 값 타입과 참조 타입은 추후에 따로 다뤄보도록 하겠습니다.
구조체 (Struct)
struct SoccerPlayer {
// Properties
var name: String // 이름
var age: Int // 나이
var club: String // 소속팀
let birthdate:String
static let isHuman: Bool = true // 타입 프로퍼티
// Methods
func dribble(){
print("dribble")
}
func pass(receiver:SoccerPlayer){
print("\(self.name) passed to \(receiver.name)")
}
func tackle(){
print("tackle")
}
// static 키워드를 붙이면 타입 프로퍼티 혹은 타입 메서드가 됩니다. 아래는 타입 메서드입니다.
static func introduceSoccer(){
print("Soccer is ...")
}
}
위 예시는 SoccerPlayer라는 구조체를 정의하는 코드입니다. 구조체도 사용자가 정의한 타입이기 때문에, struct 키워드 이후 대문자 카멜케이스로 이름을 작성해주고 그 안에는 프로퍼티와 메서드들을 작성해주면 됩니다.
var bruno : SoccerPlayer = SoccerPlayer(name:"bruno",age:28,club:"Manchester United FC",birthDate: "1993-05-21")
// var로 선언되었기 때문에 인스턴스 내부의 var로 선언된 프로퍼티 값을 변경할 수 있다.
bruno.age = 99
// 인스턴스 내부의 let으로 선언된 프로퍼티의 값은 변경할 수 없다.
// bruno.birthDate = "1994-02-21"
// Cannot assign to property: 'isHuman' is a 'let' constant
let jegyun : SoccerPlayer = SoccerPlayer(name:"Jegyun",age:25,club:"Suwon Samsung F.C.",birthDate: "1997-03-17")
// 인스턴스가 let 으로 선언되었기 때문에 내부의 프로퍼티 값을 변경하지 못한다.
// jegyun.age = 100
// Cannot assign to property: 'jegyun' is a 'let' constant
SoccerPlayer 구조체의 인스턴스를 생성하고 나서 내부의 프로퍼티에 접근하려면 마침표(.) 를 사용합니다. 메소드 또한 마찬가지입니다.
jegyun.dribble()
// "dribble"
jegyun.pass(receiver: bruno)
// "Jegyun passed to bruno"
// 타입 프로퍼티와 타입 메소드는 해당 타입에만 사용할 수 있다.
SoccerPlayer.introduceSoccer()
// "Soccer is ..."
SoccerPlayer.isHuman
// true
클래스 (Class)
클래스도 구조체와 문법적인 측면에서는 거의 비슷합니다. 예를 들어보겠습니다.
class Person {
var name: String = "someName"
var age: Int = 20
var weight: Double = 0.0
let birthDate : String = "1997-03-17"
static let isHuman: Bool = true
func sayHello(){
print("\(self.name) says Hello")
}
static func typeMethod(){
print("Type Method - static : 재정의 불가")
}
class func classMethod(){
print("Type Method - class : 재정의 가능")
}
}
마찬가지로 대문자 카멜케이스로 클래스를 작성합니다. 또한 메서드와 프로퍼티도 작성해줄 수 있습니다. 클래스의 타입 메서드에는 두 종류가 있는데, 상속 후 재정의가 가능한 class 타입 메서드, 그리고 상속 후 재정의가 불가능한 static 타입메서드가 있습니다.
var jegyun:Person = Person()
let oliver:Person = Person()
jegyun === oliver // 식별 연산자(===) 를 통해 두 변수는 다른 값을 참조하고 있음을 알 수 있다.
jegyun.name = "Jegyun"
oliver.name = "Oliver"
// 클래스의 인스턴스는 참조 타입이므로 let으로 선언되었더라도 인스턴스 프로퍼티의 값 변경이 가능
// 하지만 참조정보는 변경할 수 없음 : Cannot assign to value: 'oliver' is a 'let' constant
// oliver = jegyun
print(jegyun.name)
print(oliver.name)
jegyun.sayHello() // "Jegyun says Hello"
oliver.sayHello() // "Oliver says Hello"
// 타입 메서드 사용
Person.typeMethod() // "Type Method - static : 재정의 불가"
Person.classMethod() // "Type Method - class : 재정의 가능"
// 인스턴스에서 타입 프로퍼티 및 타입 메서드 사용 불가
// jegyun.typeMethod()
// jegyun.classMethod()
// jegyun.isHuman = false
구조체와 마찬가지로 인스턴스 생성 후 프로퍼티와 메서드를 사용합니다.
열거형 (Enum)
열거형은 연관된 항목들을 묶어서 표현하는 타입입니다. 배열이나 딕셔너리와 다르게 열거형은 처음 정의해둔 항목 값 외에는 추가/수정이 불가합니다. 스위프트의 열거형은 다른 언어의 열거형과는 다르게 많은 기능을 할 수 있습니다. 선언하는 법은 다음과 같습니다.
enum SomeEnumeration {
// enum 구현부
case something1
case something2
case something3, something4, something5
// ...
}
Swift의 열거형은 switch 구문과 함께 유용하게 쓰일 수 있습니다.
enum Week {
case mon
case tue
case wed,thu,fri,sat,sun
}
// 열거형 타입, 케이스를 모두 사용 가능
var day:Week = Week.wed
// 타입이 명확하다면 .case로 사용 가능
day = .fri
// 같은 타입인 Week의 내부 항목으로만 값 변경 가능
day = .sat
switch day {
case .mon, .tue, .wed, .thu, .fri:
print("평일")
case .sat,.sun:
print("주말")
}
열거형의 각 항목은 자체로 하나의 값이지만 원시 값(Raw Value) 도 가질 수 있습니다.
enum Sports : Int {
case baseball = 0
case soccer = 1
case basektball = 2
case football
}
// 일부 값만 원시값을 주게 되면 나머지는 Swift 가 처리함
// 정수 타입은 0부터 1씩 늘어난 값을 가짐
var num : Sports = .football
num.rawValue // 3
enum Week : String {
case mon = "월"
case tue = "화"
case wed = "수"
case thu = "목"
case fri = "금"
case sat = "토"
case sun = "일"
case someday
}
let today : Week = .wed
print("오늘은 \(today.rawValue)요일 입니다.") // 오늘은 수요일 입니다.
// 문자열 타입은 원시값을 지정해주지 않았다면, 항목 이름을 원시 값으로 가지게 됨
Week.someday.rawValue // someday
정수, 문자열 타입 뿐만 아니라 Hashable 프로토콜을 따르는 모든 타입이 원시값의 타입으로 지정될 수 있습니다.
원시값을 통해 초기화 할 수 있습니다. 원시 값을 갖는 열거형일 때, 원시 값의 정보를 안다면 원시 값을 통해 열거형 변수 또는 상수를 생성 할 수 있습니다.
// rawValue가 case에 해당하지 않을 수 있으므로 rawValue를 통해 초기화 한 인스턴스는 옵셔널 타입이다.
let monday : Week? = Week(rawValue: "월")
let tomorrow = Week(rawValue: "tomorrow") // nil
// 옵셔널 타입이므로 if let 구문을 사용할 수 있다.
if let day : Week = Week(rawValue: "tomorrow") {
print("요일 : \(day)")
} else {
print("해당하는 케이스 없음")
}
Swift의 열거형에는 메서드를 추가할 수 있습니다.
enum SoccerPosition {
case defender
case midfielder
case forward
func printPosition() {
switch self {
case .defender:
print("수비수")
case .midfielder:
print("미드필더")
case .forward:
print("공격수")
}
}
}
SoccerPosition.defender.printPosition() // 수비수
'개발🧑💻 > Swift' 카테고리의 다른 글
[Swift] 어떻게 구조체 이름이 Data냐구요 (2) | 2022.11.28 |
---|---|
[Swift] final 파헤치기 (1) | 2022.11.14 |
[Swift] 옵셔널 (0) | 2021.11.12 |
[Swift] 함수 (0) | 2021.11.09 |
[Swift] 데이터 타입 (1) - 기본 (0) | 2021.10.20 |