스위프트에서 내가 직접 타입을 정의해서 사용할 수 있다.
구조체나 클래스를 만들고 프로퍼티와 메서드를 정의해 기능을 추가할 수 있다.
- 프로퍼티 : 타입 안에 정의된 변수와 상수
- 메서드 : 타입 안에 정의된 함수
스위프트의 대부분 타입은 구조체로 이루어졌을 정도로 잘 이용되는 타입이다.
구조체를 사용할 때
- 연관된 값을 하나의 데이터 타입으로 표현하고 싶을 때
- 다른 객체나 함수에 전달 시 값을 복사하고 싶을 때
- 상속하거나 상속받을 필요가 없을 때
struct Sample {
// 가변 프로퍼티
var mutableProperty: Int = 100
// 불변 프로퍼티
let immutableProperty: Int = 100
// 타입 프로퍼티
static var typeProperty: Int = 100
// 인스턴스 메서드
func instanceMethod() {
print("instance method")
}
// 타입 메서드
static func typeMethod() {
print("type method")
}
}
구조체는 인스턴스를 생성하여 사용할 수 있다.
// 가변 인스턴스
var mutableInstance: Sample = Sample()
mutaleInstance.mutableProperty = 10
// mutaleInstance.immutableProperty = 10
// 불변 인스턴스
let immutableInstance: Sample = Sample()
// immutaleInstance.mutableProperty = 10
// immutaleInstance.immutableProperty = 10
Sample.typeProperty = 10
Sample.typeMethod()
- 불변 프로퍼티는 가변 인스턴스여도 변경이 불가능
- 불변 인스턴스는 가변 프로퍼티도 수정 불가능 (메서드는 사용 가능)
- 타입 프로퍼티와 타입 메서드는 타입으로만 사용 가능 (인스턴스로는 사용 불가)
스위프트에선 클래스이 다중상속이 지원되지 않는다!
class Student{
// 가변 프로퍼티
var mutableProperty: Int = 100
// 불변 프로퍼티
let immutableProperty: Int = 100
// 타입 프로퍼티
static var typeProperty: Int = 100
// 인스턴스 메서드
func instanceMethod() {
print("instance method")
}
// 재정의 불가 타입 메서드
static func typeMethod(){
print("type Method - static")
}
// 재정의 가능 타입 메서드
class func classMethod(){
print("class Method - class")
}
}
클래스의 타입 메서드
- static 메서드 - 재정의 불가능
- class 메서드 - 재정의 가능
var mutableInstance: Student = Student()
mutaleInstance.mutableProperty = 10
// mutaleInstance.immutableProperty = 10
let immutableInstance: Student = Student()
immutaleInstance.mutableProperty = 10
// immutaleInstance.immutableProperty = 10
- 구조체와 다르게 불변 인스턴스에서도 가변 프로퍼티는 변경 가능
- 나머지는 구조체와 동일
다른 언어에서와 달리 스위프트에선 열거형이 강력한 기능을 가질 수 있다.
enum Weekday{
case mon
case tue
case wed
case thu, fri, sat, sum
}
- case 자체가 고유한 값을 가진다
- case는 하나 또는 여러 개로 정의할 수 있다
C언어처럼 정수 값을 가지도록 하려면 rawValue를 이용하면 된다.
enum Number: Int{
case zero = 0
case one = 1
case two
case three
}
- 이름 뒤에 원시값이 가질 타입을 명시한다
- 숫자를 명시하지 않아도 자동으로 이어서 할당
- Int 뿐만이 아닌 Hashable 프로토콜을 따르는 모든 타입은 원시값의 타입으로 지정할 수 있다
var day: Weekday = Weekday.mon
day = .tue
- 열거형 case는 "열거형 타입.case"로 할당
- 이미 열거형 타입으로 지정되어 있다면 타입 이름은 생략하고 ".case"로 축약해서 사용 가능
var num: Int = Number.one.rawValue
var number: Number? = Number(rawValue: 1)
- "타입이름.case이름.rawValue"로 값을 사용할 수 있다
- 연속하지 않는 원시값 타입은 case이름 자체가 값이 된다
- rawValue로 초기화할 때는 case가 존재할 수도, 안 할 수도 있기 때문에 해당 인스턴스는 옵셔널 타입이다
열거형은 특히 switch 구문과 같이 사용되는 경우가 많다.
switch day{
case .mon, .tue, .wed, .thu:
print("평일")
case .fri:
print("금요일")
case .sat, .sun:
print("주말")
}
- case에 열거형 case를 넣어서 구분
- 열거형의 모든 case를 구분하면 default를 구현하지 않아도 된다
열거형 안에는 메서드도 정의해 사용할 수 있다.
enum Weekday{
case mon
case tue
case wed
case thu, fri, sat, sum
func printMessage() {
switch self {
case .mon, .tue, .wed, .thu:
print("평일")
case .fri:
print("금요일")
case .sat, .sun:
print("주말")
}
}
}
Month.mon.printMessage()
참조 타입 - Class
- 단일상속 (Swift에선 클래스의 다중상속이 지원되지 않음)
- Extension 가능
값 타입 - Struct, Enum
- 상속불가
- Extension 가능
struct ValueType{
var property = 1
}
class ReferenceType{
var property = 1
}
let structInstance = ValueType()
var newStructInstance = structInstance()
newStructInstance.property = 2
// structInstance.property == 1
let classInstance = ReferenceType()
var newCalssInstance = classInstance()
newCalssInstance.property = 2
// structInstance.property == 2
값 타입은 값을 복사하기 때문에 새로운 인스턴스를 만들어 프로퍼티를 변경해도 기존 프로퍼티 값엔 영향이 없다.
반면 참조 타입은 메모리의 주소를 넘기기 때문에 새로운 인스턴스의 프로퍼티를 변경하는 것은 기존 프로퍼티를 변경하는 것과 같은 행위가 된다.