11. 메서드(Method)

🌈 devleeky16498·2022년 4월 17일
0

메서드는 특정 타입과 연관된 함수이다. 클래스, 구조체, 열거형은 주어진 타입의 인스턴스 동작을 위한 특정작업과 기능을 지원하는 메서드를 정의할 수 있다. 그리고 이들은 또한 타입 자체와 연관된 타입 메서드 정의도 가능하다.

인스턴스 메서드

  1. 인스턴스 메서드는 특정 클래스, 구조체, 열거형의 인스턴스에 속하는 함수이다. 인스턴스 프로퍼티에 접근 및 수정하는 방법을 제공하며, 각종 기능을 제공한다. 인스턴스 메서드는 함수에서 설명한대로 함수구문과 완벽하게 동일하다. 또한 이는 반드시 자신이 속한 타입의 특정 인스턴스에서믄 호출 가능하다.
class Counter {
	var count = 0
    func increment() {
    	count += 1
    }
    
    func increment(by amount : Int) {
    	count =+ amount
    }
   	
    func reset() {
    	count = 0
    }
}
// Counter클래스는 3개의 인스턴스 메서드를 정의한다.
//각 인스턴스 메서드는 호출에 따라서 count프로퍼티에 대한 기능을 적용한다. 

let counter = Counter()
//인스턴스 생성
counter.increment()
//count = 1
counter.increment(by: 5)
//count = 6
counter.reset()
//count = 0

self 프로퍼티

  1. 타입의 모든 인스턴스는 인스턴스 자체와 정확하게 일치하는 self라는 암시적 프로퍼티를 가지고 있다. 자체 인스턴스 메서드 내에서 현재 인스턴스 참조를 위해 self프로퍼티를 사용하게 된다.
func increment() {
	self.count += 1
}
//다음과 같이 위의 increment메서드는 작성이 가능하다. 
//실제 코드에서는 self를 작성할 필요가 없다. self를 명시적으로 작성하지 않으면,
//Swift는 메서드 내에서 이미 알고있는 프로퍼티나 메서드를 사용할때마다
//현재 인스턴스의 프로퍼티나 메서드를 참조한다고 가정하기 때문이다.
//하지만 인스턴스 메서드에 파라미터 명이 인스턴스 프로퍼티와 동일할 때 명시해야 한다.

struct point {
	var x = 0.0, y = 0.0
    
    func isToTheRightOf(x : Double) -> Bool {
    	return self.x > x
    }
}
//리턴하는 값에서 파라미터는 그냥 x이며, 인스턴스의 프로퍼티는 self.x를 통해서 분별하였다.

인스턴스 메서드 내 값 타입 수정

  1. 사전에 언급했듯이 구조체와 열거형은 값 타입이다. 기본적으로 값 타입의 프로퍼티는 인스턴트 메서드 내에서 수정될 수 없다. 그러나 특정 메서드 내 구조체나 열거형의 프로퍼티 수정이 필요하면 해당 메서드에 대한 동작을 변경하도록 선택이 가능하다. 그러면 해당 메서드는 메서드 내 프로퍼티 변경이 가능하며, 메서드가 끝나면 기존 구조체에 변경사항이 작성된다. 이 메서드는 암시적 self프로퍼티에 새로운 인스턴스를 할당하고, 새로운 인스턴스는 메서드 종료 후 기존 존재하는 인스턴스를 대체한다. 이는 func 이전에 mutating 키워드를 위치시켜 동작하게 할 수 있다.
struct Point {
	var x = 0.0
    var y = 0.0
    
    mutating func moveBy(x deltaX : Double, y deltaY : Double) {
    	x += deltaX
        y += deltaY
    }
}

var somePoint = Point(x : 1.0, y : 1.0)
//somePoint 구조체 값을 설정한다.
somePoint.moveBy(x: 2.0, y : 3.0)
print(somePoint.x, somePoint.y)
//3.0, 4.0을 출력하게 된다.
//구조체는 값 타입으로 이를 외부 메소드로 변경할 수 없으나, 
//내부에서 메서드 값 수정을 위한 함수를 설정하여 조정이 가능하다. 
//그리고 이를 변수값으로 사전에 정의한 것도 포인트.
  1. 상수 구조체 인스턴스의 저장된 프로퍼티는 값 변경이 불가하므로, 위와 같이 메서드 호출을 통해 값 변경을 시도할 경우 에러가 발생한다.
  2. 변경 메서드에서의 self할당은 기존 인스턴스 메서드에서의 역할과 똑같이, 구조체 내 함수의 파라미터와 인스턴스 프로퍼티 간의 분별을 위해서 사용할 수 있다.
struct Point {
	var x = 0.0, y = 0.0
    
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
    	self.Point(x : X + deltaX), y : y + deltaY)
    }
}
//위와 같이 인스턴스의 프로퍼티와 메서드의 파라미터를 구분지어 작성할 수 있다.
  1. 열거형의 변경 메서드는 동일한 열거형에서 다른 케이스로 암시적 self 파라미터 설정이 가능하다.
enum TriStateSwitch {
	case off, low, high
    mutating func next() {
    	switch self {
        case .off:
        	self = .low
        case .low:
        	self = .high
        case .high:
        	self = .off
        }
}

var ovenLight = TriStateSwitch.low
ovenLight.next()
//다음과 같은 경우 .high로 변경된다.
ovenLight.next()
//다음인 .off로 변경된다.

자체 인스턴스에 대한 값을 self를 통해서 반영해준다. 

타입 메서드

  1. 위에서 설명한 인스턴스 메서드는 특정 타입의 인스턴스에서 호출하는 메서드이다. 타입 자체에서 호출되는 메서드도 정의할 수 있다. 이런 종류를 타입 메서드라고 한다. 키워드 static을 작성하여 타입 메서드를 나타낸다. 클래스는 대신 class키워드를 사용해서 하위클래스가 해당 메서드의 수퍼 클래스 구현을 재정의할 수 있다.
class SomeClass {
	class func someTypeMethod() {
    	//타입메서드가 입력된다.
    }
}

SomeClass.someTypeMethod()
//타입 메서드 바디 내 암시적 self프로퍼티는 타입 인스턴스가 아닌 타입 자체를 참조한다. 
//인스턴스 프로퍼티와 인스턴스 메서드 파라미터에서와 같이 
//self를 타입 프로퍼티와 타입메서드 파라미터를 명확하게 사용하도록 사용 가능하다.
  1. 일반적으로 타입 메서드의 바디 내에서 사용하지 않는 정규화되지 않은 메서드와 프로터피 이름은 다른 타입 레벨 메서드와 프로퍼티를 참조한다. 타입 메서드는 타입 이름을 접두어로 필요치 않고 다른 메서드 이름으로 다른 타입 메서드 호출이 가능하다.
struct LevelTracker {
	static var highestUnlockedLevel = 1
    //타입 프로퍼티
    var currentLevel = 1
    //레벨 트렉커 구조체의 프로퍼티
    
    static func unlock(_ level : Int) {
    	if level > highestUnlockedLevel {
        	highestUnlockedLevel = level
        }
    }
    
    static func isUnlocked(_ level : Int) -> Bool {
    	return level <= highestUnlockedLevel
    }
    
    @discardableResult
    mutating func advance(to level : Int) -> Bool {
    	if LevelTracker.isUnlocked(level) {
        	currentLevel = level
            return true
        } else {
        	return false
        }
    }
}
//LevelTracker구조체는 모든 플레이어가 푼 가장 높은 레벨을 추적한다.
//이 값은 highestUnlockedLevel이라는 프로퍼티에 저장된다.
//이와 더불어 위 프로퍼티와 동작하는 2개의 타입 메서드도 정의한다.
//이 타입 메서드는 LevelTracker.highestUnlockedLevel로 작성하지 않아도, 
//해당 프로퍼티에 접근이 가능하다.(타입 자체의 타입 변수이므로, 호출하지 않아도..?)
//이 외에도 각 플레이어의 진행사항을 추적한다. 
//플레이어가 현재 플레이 중인 레벨을 추적하는 currentLevel이라는 인스턴스 프로퍼티를 사용한다.
//이 currentLevel 프로퍼티 관리를 돕기 위해서 별도의 인스턴스 메서드를 정의한다.

class Player {
	var tracker = LevelTracker()
    let playerName : String
    
    func complete(level : Int) {
    	LevelTracker.unlock(level + 1)
        tracker.advance(to: level + 1)
    }
    
    init(name : String) {
    	playerName = name
    }
}

let player = Player(name: "경윤")
var tracker = LevelTracker()
tracker.currentLevel = 12
print(tracker.currentLevel)
//다음과 같이 인스턴스 생성 후 타입 변수와 메서드에 접근하려 하는 경우 에러가 발생한다.
LevelTracker.highestUnlockedLevel = 3
print(LevelTracker.highestUnlockedLevel)
//다음과 같이 인스턴스를 생성하지 않고 바로 접근할 경우 타입 변수에 접근이 가능하다.
//인스턴스를 생성한 후 해당 값으로 접근이 안되지만, 타입에 고유하게 할당되어 조작이 가능하다.
profile
Welcome to Growing iOS developer's Blog! Enjoy!🔥

0개의 댓글