궁금한 내용을 검색해보세요!
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
서근 개발노트
티스토리에 팔로잉
SWIFT/Grammar

Swift : 기초문법 [메서드 #1 인스턴스 메서드, self 프로퍼티]

서근
QUOTE THE DAY

“ 디버깅은 코드를 새로 만드는 것보다 두 배 더 어렵다. 그래서 만일 당신이 현재 공들여서 코드를 짜고 있다면, 디버깅할만큼 똑똑하지 않다는 뜻이기도 하다. ”

- 브라이언 커니건 (Brian Kernighan)
Written by SeogunSEOGUN

Swift : 기초문법 [메서드 #1 인스턴스 메서드, self 프로퍼티]

본 게시글은 Swift : 기초문법 [메서드 #1 인스턴스 메서드, self 프로퍼티]yagom님과Swift : 기초문법 [메서드 #1 인스턴스 메서드, self 프로퍼티]Zedd0202님의 게시글을 참고하여 작성되었습니다.

 

메서드(Method)

Class(클래스), Struct(구조체), Enum(열거형)에 포함되어있는 '함수'를  메서드라고 한다.

 

메서드는 다른 말로 클래스 함수라고도 한다.

 

Struct 는 내부에 함수를 가질 수 있으며, 이러한 함수는 필요에 따라 구조체의 프로퍼티를 사용할 수 있다. 구조체 내부의 함수는 methods 라고하지만 동일한 func 키워드를 사용한다.

 

클래스, 구조체 및 열거형은 특정 작업이나 기능을 캡슐화한 인스턴스 메서드에 타입 자체와 관련된 타입 메서드를 정의할 수 있다.

swift
UNFOLDED
class Person {
//이 메서드는 person 타입에만 작동(적용)됩니다.
func personGreeting() {
greet(yourName: "Santosh", category: .Person)
}
}

클래스 안에 작성되는 함수는 이제 무조건 메서드가 된다.

swift
UNFOLDED
func someFunction {
//함수 구현부
}
class someClass {
func someMethod {
//메서드 구현부
}
}

인스턴스 메서드 Instance Methods

인스턴스 메서드는 특정 Class, Struc 또는 Enum의 인스턴스에 속하는 함수이다. 인스턴스 프로퍼티의 접근 및 수정 방법 등을 제공하거나 인스턴스의 목적과 관련된 기능을 제공, 해당 인스턴스의 기능을 지원한다.

 

인스턴스 메서드는 함수와 달리 특정 타입 내부 { } 에 인스턴스 메서드를 작성한다. 따라서 인스턴스가 존재할 때만 사용 가능하다. 기존의 인스턴스가 없으면 호출 불가능하다.

  • 인스턴스 메서드가 속한 타입의 여는 중괄호 { 와 닫는 중괄호 } 안에 인스턴스 메서드를 작성
  • 인스턴스 메서드는, 다른 모든 인스턴스 메서드 및 해당 타입의 특성에 암시적으로(implicit) 접근
  • 인스턴스 메서드는 자신이 속한 타입의 특정 인스턴스에서만 호출될 수 있음
swift
UNFOLDED
class Counter {
var count = 0
func increment() {
count += 1
}
func increment(by amount: Int) {
count += amount
}
func reset() {
count = 0
}
}

Counter 라는 클래스를 정의했고, Counter 클래스는 3가지 인스턴스 메서드를 정의하고 있다.

  • increment()는 카운터를 1씩 증가시킨다.
  • increment(By: Int)는 지정된 정수만큼 카운터를 증가시킨다.
  • reset()은 카운터를 0으로 재설정한다.

프로퍼티와 마찬가지로 . 을 통해 인스턴스 메서드를 호출할 수 있다.

swift
UNFOLDED
let counter = Counter()// count = 0 (기본값)
counter.increment()//count = 1
counter.increment(by: 5)//count = 6
counter.reset()//count = 0

City 라는 구조체를 만들고, population에는 도시에 얼마나 많은 사람이 있는지 저장하는 프로퍼티와 인구수에 1000을 곱한 값을 반환하는 collectTaxes() 메서드가 있다고 가정하면

 

이 메서드는 City에 속하기 때문에 현재 도시의 인구 프로퍼티를 읽을 수 있게 된다.

swift
UNFOLDED
struct City {
var population: Int
func collectTaxes() -> Int {
return population * 1000
}
}

이 메서드는 구조체에 속하므로 다음과 같이 구조체의 인스턴스에서 호출한다.

swift
UNFOLDED
let London = City(population: 9_000_000)
london.collectTaxes()
//9000000000

또 다른 예제를 보자면, 클래스의 인스턴스 메서드에 대한 코드이다.

swift
UNFOLDED
class LevelClass {
var level: Int = 0 { //저장 프로퍼티
//값이 변경되면 실행될 프로퍼티 옵저버
didSet {
print("현재 레벨: Lv.\(level)")
}
}
func levelUp() {
print("레벨업!")
level += 1
}
func levelDown() {
print("레벨 다운")
level -= 1
if level < 0 {
reset()
}
}
func jumpLevel(to: Int) {
print("레벨이 \(to)로 점프 되었습니다.")
level = to
}
func reset() {
print("레벨이 초기화 됩니다.")
level = 0
print("레벨이 Lv.\(level)으로 초기화 되었습니다.")
}
}
var levelClassInstance: LevelClass = LevelClass()
levelClassInstance.levelUp()
//레벨업!
//현재 레벨: Lv.1
levelClassInstance.levelDown()
//레벨 다운
//현재 레벨: Lv.0
levelClassInstance.levelDown()
//레벨 다운
//현재 레벨: Lv.-1
//레벨이 초기화 됩니다.
//현재 레벨: Lv.0
//레벨이 Lv.0으로 초기화 되었습니다.
levelClassInstance.jumpLevel(to: 20)
//레벨이 20로 점프 되었습니다.
//현재 레벨: Lv.20

위에 구현한 인스턴스 메서드에는 level 인스턴스 프로퍼티 값을 수정하는 코드가 있는데, 자신의 프로퍼티 값을 수정할 때 클래스 인스턴스 메서드는 신경 쓸 필요가 없지만, 구조체 혹은 열거형은 값 타입 이기 때문에 메서드 앞에 mutating 키워드를 반드시 사용해서 해당 메서드가 인스턴스 내부의 값을 변경한다는 것을 명시해줘야 한다.

 

 

Swift : 기초문법 [메서드 #1 인스턴스 메서드, self 프로퍼티] - 메서드(Method) - 인스턴스 메서드 Instance Methods
구조체에서 속성 값을 변경하려고 할 때 나타나는 에러 메세지

swift
UNFOLDED
struct LevelStruct {
var level: Int = 0 {
didSet {
print("현재 레벨: Lv.\(level)")
}
}
mutating func levelUp() {
print("레벨업!")
level += 1
}
mutating func levelDown() {
print("레벨 다운")
level -= 1
if level < 0 {
reset()
}
}
mutating func jumpLevel(to: Int) {
print("레벨이 \(to)로 점프 되었습니다.")
level = to
}
mutating func reset() {
print("레벨이 초기화 됩니다.")
level = 0
print("레벨이 Lv.\(level)으로 초기화 되었습니다.")
}
}
var levelStructInstance: LevelStruct = LevelStruct()
levelStructInstance.levelUp()
//레벨업!
//현재 레벨: Lv.1

예시

swift
UNFOLDED
struct Pokemon {
var name: String
func attack(with attackType: String) {
print("\(name) uses \(attackType)!")
}
}
swift
UNFOLDED
struct User {
var name: String
var street: String
var city: String
var postalCode: String
func printAddress() -> String {
return """
\(name)
\(street)
\(city)
\(postalCode)
"""
}
}
swift
UNFOLDED
struct Car {
var maxSpeed: Int
func accelerate(to speed: Int) {
if speed > maxSpeed {
print("That's too fast!")
} else {
print("OK, let's go!")
}
}
}

함수와 메서드의 차이

함수를 사용하면 기능의 이름을 지정하고 반복적으로 실행할 수 있으며 Swift의 메서드는 거의 동일한 작업을 수행한다.

 

그렇다면 차이점은?

 

유일한 차이점은 메서드는 struct, enumclass 와 같은 유형에 속하지만 함수는 그렇지 않다는 것이다. 그게 유일한 차이점이다.

 

둘 다 가변 매개 변수를 포함하여 원하는 수의 매개 변수를 허용할 수 있으며 둘 다 값을 반환할 수 있다. 이 두 개는 너무 비슷해서 Swift에서는 여전히 func 키워드를 사용하여 메서드를 정의한다.

 

물론 구조체와 같은 특정 유형과 연관된다는 것은 메서드가 하나의 중요한 힘을 얻는다는 것을 의미한다. 즉, 해당 유형 내부의 다른 속성 및 메서드를 참조할 수 있다.

 

메서드 TEST: 문제를 풀려면 이곳을 클릭해주세요.

 

self 프로퍼티

타입의 모든 인스턴스는 암시적으로 생성된 self 프로퍼티를 갖는다. 이것은 인스턴스 자기 자신을 가리키는 프로퍼티이다. self 프로퍼티는 인스턴스를 더 명확히 지칭하고 싶을 때 사용하게 된다. self 프로퍼티를 사용하여 자체 인스턴스 메서드 내에서 현재 인스턴스를 참조할 수 있다.

swift
UNFOLDED
func levelUp() {
self.level += 1
}

Swift에서의 프로퍼티 사용 순서는 자동으로 메서드 내부에 선언된 지역변수메서드 매개변수인스턴스 프로퍼티 순으로 찾아 무엇을 지칭하는지 유추하게 된다.

swift
UNFOLDED
class letterClass {
var name: String = ""
func sendLetter(to name: String) {
print("\(name)에게 편지를 보냅니다.")
self.name = name
}
}
let Myletter: letterClass = letterClass()
Myletter.sendLetter(to: "서근")

위 코드를 보면 인스턴스 프로퍼티인 name과 매개변수로 넘어온 name의 이름이 같은데 여기서 self.name = nameself는 매개변수가 아닌 인스턴스 프로퍼티를 지칭한다. 쉽게 비교해보자면 아래와 같다.

Swift : 기초문법 [메서드 #1 인스턴스 메서드, self 프로퍼티] - 메서드(Method) - self 프로퍼티

self 프로퍼티의 다른 용도로는 값 타입 인스턴스 자체의 값을 치환할 수 있다. 클래스 인스턴스는 참조 타입이라 self 프로퍼티에 다른 참조를 할당할 수 없고, 구조체와 열거형은 값 타입이라 self 프로퍼티를 사용하여 자신 자체를 치환할 수 있다.

swift
UNFOLDED
class LevelClass {
var level: Int = 0
func reset() {
if level < 0 {
self = LevelClass() //Cannot assign to value: 'self' is immutable
}
}
}

↪︎ 클래스는 참조 타입이기 때문에 self 프로퍼티에 다른 참조를 할당할 수 없기에 error

swift
UNFOLDED
struct LevelStruct {
var level: Int = 0
mutating func levelUp() {
print("레벨업!")
level += 1
}
mutating func reset() {
print("초기화!")
self = LevelStruct()
}
}
var levelStructInstance: LevelStruct = LevelStruct()
levelStructInstance.levelUp() //레벨업!
print("현재 레벨 : Lv.\(levelStructInstance.level)") //현재 레벨 : Lv.1
levelStructInstance.reset() //초기화!
print("현재 레벨 : Lv.\(levelStructInstance.level)") //현재 레벨 : Lv.0

↪︎ 구조체에서 reset 메서드의 self 프로퍼티는 LevelStruct의 기본 값이 있는 인스턴스 프로퍼티 level = 0으로 할당이 되었기 때문에 reset 메서드를 호출할 때 현재 레벨이 0이 된다.

swift
UNFOLDED
enum OnOffSwitch {
case on, off
mutating func nextState() {
self = self == .on ? .off : .on
}
}
var toggle: OnOffSwitch = OnOffSwitch.off
toggle.nextState()
print("현재 스위치 상태 : \(toggle)")
//현재 스위치 상태 : on

↪︎ 배열 내의 nextState 메서드를 보면 삼항 연산자를 사용했는데, self(OnOffSwitch)는 self(OnOffSwitch)가 .on이라면 .Off로 타입을 변경, 그게 아니라면 .on으로 변경으로 할당해줬다.

Swift : 기초문법 [메서드 #1 인스턴스 메서드, self 프로퍼티] - 메서드(Method) - self 프로퍼티

TIP
 
 

self 인스턴스
저장 인스턴스와 매개변수 이름이 같다면 반드시 self를 붙혀 해당 타입의 저장 프로퍼티 인스터스 프로퍼티인지 구별해줘야 한다

 

 

읽어주셔서 감사합니다🤟

 

 

 


잘못된 내용이 있으면 언제든 피드백 부탁드립니다.


서근


위처럼 이미지 와 함께 댓글을 작성할 수 있습니다.