일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 흐름도
- 깃허브
- github란
- ios
- swift
- 스위프트
- APNS
- git이란
- git사용법
- 순서도
- UIViewController
- 정규식
- 플로우 차트
- github
- git
- Regex
- 정규표현식
- 깃
- flow chart
- OS
- flowchart
- JSONSerialization
- Git과 Github차이점
- 플로우차트
- PushNotification
- 계산기
- xcode
- 애플
- GitvsGithub
- 백준
- Today
- Total
Diana의 iOS 개발일기
[스위프트 프로그래밍 3판] - 9. 구조체와 클래스 본문
구조체와 클래스는 프로그래머가 데이터를 용도에 맞게 묶어 표현하고자 할 때 유용합니다.
함수형 프로그래밍인 스위프트에서는 각각의 함수들은 독립적이며 이를 어떻게 구조화하여 코딩하는지에 따라 프로그램의 퀄리티가 달라지는데 이러한 함수, 메서드 들을 묶어 표현하는 것이 구조체와 클래스이므로 이 둘을 잘 이해하는 것은 꽤나 중요합니다.
[구조체 - Structure Type]
struct MyTest { //struct 구조체이름
var first: String
var second: Int
//프로퍼티와 메서드들
}
구조체의 기본 구조는 위와 같이 struct 키워드를 사용하여 정의합니다.
구조체를 생성할 때 프로퍼티들의 초기값을 지정하지 않았다면 선언 시 전달인자로 초기 값을 넘겨주어야 합니다.
글로만 보면 이해도 안되고 헷갈릴 수 있으니 코드를 봅시다.
struct MyTest {
var first : String = "Hi"//초기 값을 줌
var second : Int = 0
}
var mySample : MyTest = MyTest() //전달인자를 넘기지 않아도 됨
//-------------------------------------------------------------------------
struct MyTest {
var first : String //초기 값을 주지 않음
var second : Int
}
var mySample : MyTest = MyTest(first : "Hi", second : 0) //전달인자를 넘겨야 함
그러면 왜 위와 같이 프로퍼티는 초기 값이 주어져야 할까요?
이유는 바로 프로퍼티는 기본, 옵셔널이 아닌 값으로 설정되어있습니다. 즉, 옵셔널로 설정하게 되면 초기 값을 주지 않아도 된다는 뜻이 되죠. 참고로 클래스 또한 같은 특징을 가지고 있으므로 기억해둘 필요성이 있습니다.
인스턴스가 생성 되고 구조체의 프로퍼티에 접근 하기 위해서는 마침표(.)를 사용하면 됩니다.
이때 구조체는 let 과 var 로 선언될 수 있는데 구조체의 인스턴스는 클래스와 달리 값 타입이므로 let으로 선언했을 경우 내부 프로퍼티들을 변경할 수 없습니다.
var mySample : MyTest = MyTest(first : "Hi", second : 0)
mySample.first = "Hello" //변경 가능
//-----------------------------------------------------
let mySample : MyTest = MyTest(first : "Hi", second : 0)
mySample.first = "Hello" //오류!
[클래스 - Class]
class MyTest { //class 클래스이름 : 부모클래스이름(생략 가능)
var first : String = "Hi"
var second : Int = 0
}
클래스의 기본 구조는 위와 같이 class 키워드를 사용하여 정의합니다. 확실히 구조체와 꽤 비슷하네요.
클래스 또한 생성 시 프로퍼티들의 초기값을 지정하지 않았다면 선언 시 전달인자로 초기값을 넘겨주어야 합니다.
class MyTest {
var first : String = "Hi"//초기 값을 줌
var second : Int = 0
}
var mySample : MyTest = MyTest() //전달인자를 넘기지 않아도 됨
//-------------------------------------------------------------------------
class MyTest {
var first : String //초기 값을 주지 않음
var second : Int
}
var mySample : MyTest = MyTest(first : "Hi", second : 0) //전달인자를 넘겨야 함
참고로 클래스와 구조체의 이름은 대문자 카멜케이스를 따릅니다. 그 외 메소드, 변수, 인스턴스 등의 이름은 소문자 카멜케이스에 따라 명명합니다.
클래스의 프로퍼티 또한 접근을 위해서는 마침표(.)를 사용합니다.
하지만 구조체와 달리 클래스의 인스턴스는 참조타입이므로 let으로 선언하더라도 내부 프로퍼티 값을 변경할 수 있습니다.
var mySample : MyTest = MyTest(first : "Hi", second : 0)
mySample.first = "Hello" //변경 가능
//-----------------------------------------------------
let mySample : MyTest = MyTest(first : "Hi", second : 0)
mySample.first = "Hello" //변경 가능
참조타입인 클래스는 더이상 참조할 필요가 없을 때 메모리에서 해제 되는데 이를 소멸이라고 부릅니다.
소멸은 deinit이라는 메서드를 호출하여 이루어지며 이 메서드를 디이니셜라이저(Deinitializer)이라고 부릅니다.
해당 소멸 메서드는 클래스당 한개만 구현할 수 있으며 매개변수를 위한 소괄호를 적지 않습니다.
값 타입 vs 참조 타입
그럼 이제 구조체와 클래스의 중요한 차이점인 값 타입과 참조 타입에 대해 좀더 알아보도록 하겠습니다.
구조체의 특징인 값 타입은 전달인자로 값을 넘긴다면 전달될 값이 복사되어 전달됩니다. 반면, 클래스의 특징인 참조 타입은 전달인자로 전달될 때 값이 복사되는 것이 아닌 참조(주소)가 전달됩니다.
주소가 전달된다? 언뜻 보면 헷갈리는 말입니다. 하지만 C나 Objective-C 등 언어의 포인터 개념을 조금이나마 알고있으면 이해하기 쉬워집니다.
설명을 해보자면 A라는 이름의 집에 P라는 사람이 산다고 칩시다.
구조체의 경우 값을 할당할 때 P라는 사람이 아닌 P와 똑같이 생긴 인형 P'을 하나 만든 후 집에서 데리고 나와 B로 변경합니다.
따라서 A라는 집에 P가 살고 있다는 사실은 변하지 않죠.
하지만 클래스의 경우 집 A의 집주소를 가져와 집주소를 가리키며 저 안에 있는 사람 데려가서 바꿔!라고 합니다.
그 안에는 P라는 사람이 있으니 P라는 사람은 집에서 쫒겨나고 다른 B가 들어와 살게되죠.
이후 집 A안에 있는 사람이 누군지를 출력해보면 구조체의 경우는 사람 P가 살고있을 것이고 클래스의 경우는 사람 B가 살고있을 것입니다.
struct MyTest {
let first : String = "Hi"
var second: Int = 0
}
var myInfo : MyTest = MyTest(first: "Hello", second: 100)
myInfo.first = 500
//yourInfo는 MyTest의 복사본, 즉 인형이네요
var yourInfo : Mytest = myInfo
yourInfo.first = "Bye" //인형을 변경한 것이니 원래 사람은 그대로 있겠죠?
//-------------------------------------------------------
class MyTest {
let first : String = "Hi"
var second: Int = 0
}
var myInfo : MyTest = MyTest(first: "Hello", second: 100)
myInfo.first = 500
var yourInfo : Mytest = myInfo //yourInfo는 집주소를 가리킵니다.
yourInfo.first = "Bye" //저 집에 살고 있는 녀석을 Bye라고 바꿔!
print("myInfo.first = \(myInfo.first)") //결과는 "Bye"가 되네요
해당 글은 야곰님의 스위프트 프로그래밍 3판 을 기반으로 한 정리 글이며 문제가 있을 시 삭제하도록 하겠습니다.
스위프트 프로그래밍 3판 eBook 구매 링크: www.yes24.com/Product/Goods/81530016
야곰님의 블로그: blog.yagom.net/
'Swift > 책 정리' 카테고리의 다른 글
[스위프트 프로그래밍 3판] - 14. 옵셔널 체이닝과 빠른 종료 (1) | 2021.03.17 |
---|---|
[스위프트 프로그래밍 3판] - 13. 클로저 (0) | 2021.03.11 |
[스위프트 프로그래밍 3판] - 12. 접근제어 (0) | 2021.03.10 |
[스위프트 프로그래밍 3판] - 11. 인스턴스 생성 및 소멸 (0) | 2021.03.09 |
[스위프트 프로그래밍 3판] - 10. 프로퍼티와 메서드 (0) | 2021.03.08 |