일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 흐름도
- git
- git이란
- Regex
- flow chart
- git사용법
- Git과 Github차이점
- 정규식
- PushNotification
- GitvsGithub
- github
- 순서도
- github란
- ios
- 플로우차트
- OS
- 정규표현식
- swift
- 계산기
- xcode
- 플로우 차트
- 깃
- 깃허브
- 백준
- 애플
- UIViewController
- 스위프트
- APNS
- flowchart
- JSONSerialization
- Today
- Total
Diana의 iOS 개발일기
[스위프트 프로그래밍 3판] - 10. 프로퍼티와 메서드 본문
스위프트를 공부하면 자주 보게되는 단어 중 하나가 바로 프로퍼티가 아닐까 싶습니다.
그만큼 프로퍼티에 대해 잘 알아놓아야 스위프트 코드를 이해하기 쉬워지죠.
처음 스위프트를 공부하기 시작했을 때는 프로퍼티 == 변수, 상수 라고 생각하였는데 공부를 함에 따라 프로퍼티에는 다양한 종류가 있고 변수와 상수는 단지 그 중 하나라는 것을 알게되었습니다.
[프로퍼티 - Property]
프로퍼티는 크게 세가지 종류로 나눌 수 있습니다.
- 저장 프로퍼티(Stored Properties)
- 연산 프로퍼티(Computed Properties)
- 타입 프로퍼티(Type Properties)
1. 저장 프로퍼티(Stored Properties)
저장 프로퍼티는 클래스 또는 구조체의 인스턴스 변수를 말하며 var과 let의 키워드를 사용할 수 있습니다.
struct MyTest { //기본적으로 이니셜라이저가 생성되므로 메모리가 따란~ 생기네요
var first : String
var second : Int
}
let myPoint : MyTest = MyTest(first: "Hi", second: 0)
class MyTestNumber {
var testNumber : MyTest
let testName : String
//메모리를 직접 할당해줘야 합니다!
init(testName: String, currentNumber : MyTest) {
self.testName = testName
self.point = MyTest
}
}
//메모리를 잡아주었으니 인스턴스를 할당할 수 있습니다
let myNumber : MyTestNumber = MyTestNumber(testName: "Test", currentNumber: myPoint)
구조체와 클래스의 저장 프로퍼티의 사용은 위와 같은데 이 둘 사이에는 차이점이 있습니다.
우선 구조체는 저장 프로퍼티가 옵셔널이 아니더라도, 저장 프로퍼티를 모두 포함하는 이니셜라이저를 자동으로 생성합니다. 하지만 클래스의 저장 프로퍼티는 옵셔널이 아니라면 프로퍼티 기본값을 지정해주거나 사용자 정의 이니셜라이저를 통해 반드시 초기화 해주어야 합니다.
아니 이게 대체 뭔소릴까요?
간단히 이야기하면 C의 malloc()과 비슷한 내용으로 구조체의 저장 프로퍼티 같은 경우는 사용을 하면 이니셜라이저를 자동 생성, 즉 메모리를 따란~ 하고 확보해줍니다.
하지만 클래스의 저장 프로퍼티의 경우는 사용을 했을 때 초기값을 지정해 메모리를 확보해 주지 않는 이상 자동으로 메모리가 생성이 안되며 우리가 직접 init을 통해 메모리 공간을 확보한 뒤 할당해 주어야 합니다.
1-2. 지연 프로퍼티(Lazy Property)
스위프트에는 지연 프로퍼티 라는 프로퍼티가 있습니다.
보통의 프로퍼티들은 구조체나 클래스의 인스턴스가 생성되어 초기화 되는 순간 메모리가 할당됩니다.
하지만 구조체나 클래스의 인스턴스를 생성하더라도 그 내부에 있는 프로퍼티들을 모두 사용하는 것은 아닌데 이 경우 메모리에는 사용되지 않는 프로퍼티가 올라감에 따라 메모리 낭비가 이루어집니다.
하지만 지연 프로퍼티의 경우 프로퍼티 본인이 호출되지 않는 이상 메모리 할당이 이루어지지 않아 메모리 낭비를 막아주는 꽤나 착한 프로퍼티입니다.
class LazyTest {
var first : Int = 0 //초기화를 해줌으로써 메모리가 할당됨
lazy var late : String = "Hi" //초기화를 해줬지만 아직 호출 전이므로 메모리 할당 X
}
let lazy = LazyTest()
lazy.late //호출되었으므로 이제서야 메모리가 할당됨
2. 연산 프로퍼티(Stored Properties)
연산 프로퍼티는 앞의 저장 프로퍼티와는 다르게 실제 값을 저장하는 프로퍼티가 아니라, 특정 상태에 따른 값을 연산하는 프로퍼티입니다.
연산을 위해서는 메서드를 사용할 수 도 있는데 메서드가 아닌 연산 프로퍼티를 사용하는 이유는 간단합니다.
메서드의 경우 인스턴스 외부에서 메서드를 통해 인스턴스 내부 값을 접근하려면 접근자와 설정자, 즉 getter, setter메서드 이 두 개가 필요합니다. 결국 코드는 분산 구현되고 가독성은 떨어질 수 밖에 없죠.
따라서 스위프트에서는 연산 프로퍼티를 사용함으로 써 좀 더 알아보기 쉽고 직관적인 코드를 사용하는 쪽을 더 선호합니다.
struct CoordinatePoint {
var x : Int
var y : Int
var oppositePoint: CoordinatePoint{ //연산을 위한 프로퍼티! 연산프로퍼티
//접근자
get {
return CoordinatePoint(x: -x, y: -y)
}
//생성자
set(opposite){
x = -opposite.x
y = -opposite.y
}
}
}
var myPosition: CoordinatePoint = CoordinatePoint(x: 10, y: 20)
print(myPosition) //10, 20
print(myPosition.oppositePoint) //-10, -20
//인스턴스 외부에서 인스턴스 내부에 접근
myPosition.oppositePoint = CoordinatePoint(x: 15, y: 10)
print(myPosition) //-15, -10
위의 코드는 연산프로퍼티를 사용하여 구조체 CoordinatePoint를 작성한 것 입니다. 그럼 연산 프로퍼티가 아닌 메서드를 사용해서 같은 기능을 구현하면 어떻게 될까요?
struct CoordinatePoint {
var x: Int
var y: Int
//접근자
func oppositePoint() -> Self{//Self는 자기자신, 즉 CoordinatePoint를 나타냅니다.
return CoordinatePoint(x: -x, y: -y)//return 생략 가능
}
//설정자
mutating func setOppositePoint(_ opposite: CoordinatePoint) {
x = -opposite.x
y = -opposite.y
}
}
연산프로퍼티를 사용하면 프로퍼티 하나로 끝날텐데 많이 복잡해졌네요.
2-1. 프로퍼티 감시자(Property Observer)
프로퍼티 감시자는 프로퍼티의 값이 변경될 때 마다 호출되는 프로퍼티를 말합니다.
프로퍼티의 값이 변경되기 직전에 호출하는 willSet 메서드와 didSet 메서드로 구성되어 있으며 willSet메서드에 전달되는 전달인자는 프로퍼티가 변경될 값이고, didSet메서드에 전달되는 전달인자는 프로퍼티가 변경되기 전의 값입니다.
class Account {
var credit: Int = 0 {//프로퍼티가 변경되지 않으면 0부분에서 멈추고 아래 감시자는 호출되지 않습니다
willSet{//값이 지정되기 직전에 호출
//newValue는 자동 지정된 매개변수 명
print("잔액이 \(credit)원에서 \(newValue)원으로 변경될 예정입니다")
}
didSet {//값이 지정된 직후에 호출
print("잔액이 \(oldValue)원에서 \(credit)원으로 변경되었습니다")
}
}
}
let myAccount: Account = Account()
myAccount.credit = 1000 //프로퍼티 값이 새로 할당되었으므로 프로퍼티 감시자가 호출됩니다.
3. 타입 프로퍼티(Type Property)
타입 프로퍼티는 타입 자체에 속하는 프로퍼티를 의미합니다.
static 키워드를 사용해서 나타내며 그 타입의 모든 인스턴스가 공통으로 사용하는 값, 모든 인스턴스에서 공용으로 접근하고 값을 변경할 수 있는 변수를 정의할때 유용합니다. 약간 Java의 static과 비슷해 보이네요.
타입 자체에 속하는 프로퍼티? 무슨소릴까요? 예제 코드를 확인해 보겠습니다.
class AClass {
//저장 타입 프로퍼티
static var typeProperty : Int = 0
//저장 인스턴스 프로퍼티
var instanceProperty : int = 0 {//프로퍼티 감시자가 붙어있네요
didSet {
Self.typeProperty = instanceProperty + 100
}
}
//연산 타입 프로퍼티
static var typeComputeProperty : Int {//아래 형식을 보아하니 연산을 하고있죠?
get{
return typeProperty
}
set {
typeProperty = newValue
}
}
}
AClass.typeProperty = 123
let classInstance : AClass = AClass()
classInstance.instanceProperty = 100 //인스턴스 프로퍼티는 인스턴스를 생성을 하여야 사용 가능
//타입 프로퍼티는 인스턴스 생성 없이 프로퍼티를 사용할 수 있다
print(AClass.typeProperty) //200
print(AClass.typeComputeProperty) //200
예제 코드를 보니 타입 프로퍼티는 인스턴스 생성 없이도 프로퍼티를 사용할 수 있습니다.
하지만 주의해야 할 점이 있다면 저장 타입 프로퍼티는 변수와 상수 둘 다로 선언될 수 있는 반면에 연산 타입 프로퍼티는 변수로만 선언이 가능합니다.
a. 메서드 - Method
이제 마지막으로 프로퍼티 관점에서 인스턴스 메서드와 타입 메서드를 알아보겠습니다.
인스턴스 메서드는 함수와 문법이 같으나 함수와 달리 특정 타입 내부에 구현함으로써 인스턴스가 존재할 때만 사용할 수 가 있습니다.
특정 타입의 내부에 존재한다? 간단합니다.
class LevelClass {
var level : Int = 0 {//프로퍼티 감시자입니다
didSet {
print("Level \(level)")
}
}
func leveUp() { //class라는 타입 안에 메서드가 존재하네요. 인스턴스 메서드 입니다
print("Level up!")
level += 1
}
func levelDown() {
print("Level down")
level -= 1
if level < 0 {
reset()
}
}
func jumpLevel(to: Int) {
print("Jump to \(to)")
level = to
}
func reset() {
print("Reset!")
level = 0
}
}
var levelClassInstance: LevelClass = LevelClass()
levelClassInstance.leveUp() //Level up!
//Level 1
levelClassInstance.levelDown() //Level Down
//Level 0
levelClassInstance.levelDown() //Level Down
//Level -1
//Reset!
//Level 0
levelClassInstanve.jumpLevel(to: 3) //Jump to 3
//Level 3
즉 위의 예시와 같이 levelUp, levelDown등의 함수는 타입 안에 존재하는 메서드로 인스턴스 메서드라고 볼 수 있습니다.
b. 타입 메서드 - Type Method
프로퍼티에 타입 프로퍼티가 있듯이 메서드에도 타입 메서드가 있습니다. 메서드 앞에 static 키워드를 사용하여 타입 메서드임을 나타냅니다.
static 키워드로 메서드를 정의하면 상속 후 메서드 재정의, 즉 오버라이드가 불가능하고 class로 정의하면 상속후 메서드 오버라이드가 가능합니다.
해당 글은 야곰님의 스위프트 프로그래밍 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판] - 9. 구조체와 클래스 (0) | 2021.03.08 |