본문 바로가기

기능

[Swift]인스턴스메서드와 타입메서드의 개념과 차이점

주의 : 영문서 번역 중 오역이 있을 수 있으며 정확하지않는 정보가 있을 수 있습니다.

 

인스턴스메서드와 타입메서드의 차이는 무엇일까 ?

Swift Language Guide를 참고한 인스턴스 메서드 설명

 

인스턴스 메서드란 특정한 enum 이나 struct, class의 인스턴스로 속해 있는 함수이다. 그것은 인스턴스를 돕기위한 기능이고 프로퍼티인스턴스를 수정하고 접근하는 방법을 제공하거나 또는 인스턴스를 연결시키는 기능으로써 사용된다. 인스턴스메서드는 정확히 함수의 구문과 정확이 일치한다.

Swift Language Guide를 참고한 타입 메서드 설명

인스턴스 메서드는 위에서본것과 같이 특정 타입의 인스턴스 위에서 호출을 할 수 있다. 근데 타입메서드는 타입자체위에서 호출할 수 있다.

이런걸 타입메서드라도 부르며 이는 함수 func 앞에 static이라고 써줌으로써 나타낼 수 있다. Class는 키워드 앞에 class라고 사용할 수 있고, class를 붙여 사용하는 메서드는 subclass를 할때 superclass를 재정의하여 구현할 수 있다.

 

직접 선언해서 사용해보자.

 

인스턴스 메서드 구현

struct User {
    // MARK : - Properties
    let name: String
    
    // MARK : - Instance Methods
    func greeting() -> String {
        "Hello \(name)"
    }
}
// 인스턴스 생성
let quokka = User(name: "quokka")
// quokka인스턴스 호출
print(quokka.greeting())

// 오류발생
User.greeting()

오류발생 - Instance member 'greeting' cannot be used on type 'User'; did you mean to use a value of this type instead?

해석 - 인스턴스 메서드 greeting을 타입으로써 사용할 수 없다. 너는 인스턴스 타입의 값을 사용하는의미에 대해 알고있냐 ? 라는 에러가나온다.

 

사용할 수 없는 이유는 간단하다. 일단 greeting메서드는 타입메서드가 아니기때문이고, User라는 타입의 인스턴스를 생성하여 호출할 수 있는 인스턴스 메서드이기때문이기때문에 타입메서드로써 사용할 수 없는것이다.

 

 

그러면 인스턴스메서드는 인스턴스를 생성해야만 접근할 수 있는거라면 타입메서드는 뭔데 ?

우리는 위에서 인스턴스메서드는 타입메서드로서 부를 수 없다는것을 배웠다. 그래서 우리는 타입메소드는 무엇인지 ? 에대해서 질문을 던져 차이점을 설명할 수 있게 타입메서드를 생성해볼것이다. 참고로 타입 메서드를 생성할때는 메서드앞에 'static'이라는 단어를 붙인다.

타입메서드 구현

struct User {
    // MARK : - Properties
    let name: String
    
    // MARK : - Instance Methods
    func greeting() -> String {
        "Hello \(name)"
    }
    
    static func createUser(with name: String) -> User {
        User(name: name)
    }
}

let quokka = User(name: "quokka")
print(quokka.greeting())

let kayn = User.createUser(with: "kayn")
print(kayn)
// 오류발생
quokka.createUser(with: "quokka")

오류발생 - Static member 'createUser' cannot be used on instance of type 'User'

해석 - Static 멤버인 createUser메서드는 타입 User라는 인스턴스 위에서 사용될 수가 없다. 즉 인스턴스 메서드가 아니고 타입메서드 이기때문에 인스턴스로 사용될 수 없다는 의미같다.

 

위에 공식문서에 내용과 같이 인스턴스가 아닌 타입 메서드이기때문에 인스턴스를 생성할 필요가 없는것이다. 고로 바로 접근가능

 

그럼 class타입메서드는 어떠한가 ?

class Book {
    // MARK: Properties
    
    let title: String
    let author: String
    
    //MARK: - Initialization
    
    init(title: String, author: String) {
        self.title = title
        self.author = author
    }
    
    // MARK: Type Methods
    static func favorites() -> [Book] {
        [Book(title: "말그릇", author: "김윤나")]
    }
    
    class func moreFavorited() -> [Book] {
        [Book(title: "신경끄기의기술", author: "마크 맨슨")]
    }
}

print(Book.favorites())
print(Book.moreFavorited())
//[WhatIsTheInstanceMethodAndStaticMethod.Book]
//[WhatIsTheInstanceMethodAndStaticMethod.Book]

 

둘다 같은 의미로 사용되는건가 ?? 타입메서드로 사용된다는것과 사용법도 알겠는데 굳이 두개를 나눠놧을리는 없을것이다.

차이점은 무엇일까?

 

 

class FantasyBook: Book {
    override static func favorites() -> [Book] {
        [Book(title: "재정의안됨", author: "static")]
    }
    override class func moreFavorited() -> [Book] {
        [Book(title: "재정의가능", author: "class")]
    }
}

오류 발생 - Cannot override static method

해석 - static 메서드는 재정의를 할 수 없다고 나온다. 왜 클래스는 같은타입인데 class 타입메서드는 재정의가 가능하고 static 타입메서드는 재정의가 불가능할까 ? -> class는 타입으로 써 사용이되면서도 상속이 가능한 타입인데 static은 단순히 타입으로써만 사용이 가능할 수 있도록 설계가 되었기때문

 

포인트 정리

- 타입메서드를 선언하려면 메서드앞에 static 또는 class를 붙여주면된다

- 인스턴스 메서드란 타입내에 있는 메서드로써, 인스턴스를 생성하여 접근 할 수 있는 메서드를 말한다.

- 타입메서드는 인스턴스 메서드가 아니고 타입메서드이기때문에 타입으로써 접근해야한다.

- 타입메서드로 static과 class도 사용될 수 있다. (struct, enum 타입 메서드도 가능한지 시도해봤으나 사용불가, 이유는 상속을 지원하 지 않기때문)

- static타입메서드와 class타입메서드의 차이점은 subclassing을 했을때 static타입메서드는 override(재정의)가 불가하고 class타입메서드만 override할 수 있었다.

 

[참고자료]

[cococats](https://cocoacasts.com/swift-fundamentals-what-is-the-difference-between-instance-methods-and-type-methods-in-swift)

[공식문서](https://docs.swift.org/swift-book/LanguageGuide/Methods.html#ID241)