선언 방식
구조체는 타입을 정의하기때문에 대문자 카멜케이스를적용
struct 이름 {
멤버
타입 멤버
인스턴스 메서드
타입 메서드
}
어떤 타입안의 멤버를 프로퍼티, 함수를 메소드 라고 부름
타입 프로퍼티는 뭐고 타입 메서드는 머지? 무슨 차이가 있는 걸까?
타입이 붙으면 static이 앞에 붙넹
struct Sample {
var propertyOne: Int = 100
let propertyTwo: Int = 42
static var typeProperty: Int = 1
func instanceMethod() {
print("instance method")
}
static func typeMethod() {
print("type method")
}
}
static 키워드를 붙여주게 되면 Sample이라는 타입에서
사용할수있는 타입 프로프티가 됩니다.
static이 없다면 인스턴스
함수도 마찬가지
구조체 사용법
struct Sample {
var propertyOne: Int = 100
let propertyTwo: Int = 42
static var typeProperty: Int = 1
func instanceMethod() {
print("instance method")
}
static func typeMethod() {
print("type method")
}
}
var 이름: Sample = Sample()
이렇게 구조체가 하나의 타입이 되었음
하나의 인스턴스가 생성이 된다
앞에 var가 붙었기 때문에 내부 프로퍼티 값들을 변경 할 수있다
이름.propertyOne = 200
이름.instanceMethod()
// let으로 선언된 놈은 바꿀수 없다
// 불가능 -> 이름.propertyTwo = 200
타입 자체가 사용할수 있는 프로퍼티, 타입 자체가 사용할 수 있는 메소드
구조체 선언부에 static을 붙여 선언한 것들
Sample.typeProperty = 10
Sample.typeMethod()
-> 인스턴스를 거치는게 아니라 타입 자체로 사용할 수 있음!
// 이름.typeProperty = 400
// 이름.typeMethod()
// -> 이렇게 인스턴스가 타입 프로퍼티나 메소드를 사용하는건 불가능
struct Student {
var name: String = "unknown"
var `class`: String = "Swift" // ``로 묶어주면 class라는 이름도 사용가능해짐
static func selfIntroduce() {
print("학생타입입니다.")
}
func selfIntroduce() {
print("저는 \\(self.class)반 \\(name)입니다")
}
}
class는 이미 정의된 키워드이기 때문에 이를 변수이름으로
사용하고싶다면 ``으로 감싸줘야 하고
사용할때도 self.class로, 명시적으로 앞에 self.을 붙여줘야 사용할 수 있다
선언 방식
클래스는 구조체와 매우 유사
구조체는 값 타입인 반면 클래스는 참조타입이라는 점이 큰 차이
'다중 상속'이 되지 않는다는점 유의(상속은 됨)
class 이름 {
구현부
}
class Sample {
var propertyOne: Int = 100
let propertyTwo: Int = 10
static var typeProperty: Int = 42
func instanceMethod() {
print("instance method")
}
static func typeMethod() {
print("type method - static")
class func classMethod() {
print("type method - class")
}
}
구조체와 매우 유사함을 볼 수 있음
다만, 차이점은 인스턴스메서드, 타입메서드에 추가로 클래스 메서드라는게 있다
나중에 상속을 받았을때 재정의 불가능한 static
재정의가 가능한 class
둘다 타입 메서드라고 부르긴하는데 선언부에 어떤 키워드가 붙냐에 따라 다르다
사용 방식
class Sample {
var propertyOne: Int = 100
let propertyTwo: Int = 10
static var typeProperty: Int = 42
func instanceMethod() {
print("instance method")
}
static func typeMethod() {
print("type method - static")
class func classMethod() {
print("type method - class")
}
}
var sample: Sample = Sample()
sample.propertyOne = 200
// let 으로 선언된 프로퍼티 변경 불가능
// sample.propertyTwo = 100
let sample2: Sample = Sample()
sample2.propertyOne = 200
// let으로 선언된 클래스라도 프로퍼티가 변수로 선언되어있으면
// 수정 가능!!!
즉, let, var 인스턴스의 키워드 상관없이 내부 var 프로퍼티는 변경해줄 수 있음
열거형 enum
굉장히 강력한 기능을 가질수있음!
잘알면 훨씬 도움됨
각각의 케이스가 고유의 값으로 취급된다
C경우 정수값이 자동할당되었음 Swift에선 전혀 그렇지않다
enum은 타입이므로 대문자 카멜케이스를 사용해서 이름을 정의
각 케이스는 소문자 카멜케이스로 정의한다
케이스는 그 자체가 고유의 값이다(무슨뜻?)
enum 이름 {
case 이름1
case 이름2
case 이름3, 이름4, 이름5
...
메서드
}
enum Weekday {
case mon
case tue
case wed
case thu, fri, sat, sun
}
요일들을 만들어보았다
각자 한줄씩 넣어줄수도, 한줄에 다 넣어줘도 됨
열거형의 케이스를 나타내는 문법은?
var day: Weekday = Weekday.mon
var day = Weekday.mon
day = .tue
열거형은 스위치 케이스문에 자주 사용됨
switch day {
case .mon, .tue, .wed, .thu:
print("It is weekday")
case Weekday.fri:
print("TGIF")
case .sat, .sun:
print("Happy weekend")
}
이렇게 case 뒤에 타입을 명시하고 값을 줄수도, .으로 생략하고
값을 줄수도 있다
케이스를 전부 구현해주면 default를 구현해줄 필요없다
그러나 하나라도 빼주면 default를 구현 해줘야한다
.rawValue
C처럼 각 케이스에 값을 주고 싶다면?
열거형 정의시 rawValue(원시값)을 줄 수 있다.
enum 이름 {
case 이름1
case 이름2
case 이름3, 이름4, 이름5
...
}
이 포맷에 원시값의 자료형과 값을 넣어주되,
케이스별로 각각 다른 값을 가져야 한다
enum 이름: 자료형 {
case 이름1 = 0
case 이름2 = 1
case 이름3 (자동으로 1씩 증가함)
...
}
enum Fruit: Int {
case apple = 0
case grape = 1
case peach
}
print("peach's rawvalue is \\(Fruit.peach.rawValue)")
정수 타입 뿐만 아니라 Hashable프로토콜을 따르는 모든 타입이 원시값의 타입으로 지정될 수 있다
enum School: String {
case elementary = "초등"
case middle = "중등"
case high = "고등"
case university
}
print("university rawvalue is \\(School.university.rawValue)")
// university rawvalue is university
// 숫자는 1씩 증가해서 예상되지만 문자열의 경우는 케이스의 이름 자체를 가져옴
rawValue를 통해 초기화 할 수 있다(?무슨뜻)
rawValue가 case에 해당하지 않을 수 있으므로
rawValue를 통해 초기화 한 인스턴스는 옵셔널 타입이다
let apple: Fruit = Fruit(rawValue: 1)
이런식으로 초기화 할수 있다고~ 아하! 그런데
let apple: Fruit? = Fruit(rawValue: 0)
이렇게 케이스가 정의되지 않은 rawValue값이 들어올 수도 있으니까
그런 경우를 대비하기 위해 옵셔널인 ?로 써야한다는거구나
값을 쓰고싶으면 if let으로 옵셔널 바인딩을 거쳐 사용할 수 있겠네
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 {
case .mar, .apr, .may:
print("봄")
case .jun, .jul, .aug:
print("여름")
case .sep, .oct, .nov:
print("가을")
case .dec, .jan, .feb:
print("겨울")
}
}
}
Month.mar.printMessage()
인스턴스를 생성하지 않더라도 함수호출을 할 수 있다...!
클래스는 참조타입. 열거형과구조체는 값 타입이라는 것이 가장 큰 차이점이다
클래스는 상속이 가능하지만 열거형과 구조체는 상속이 불가능하다