본문 바로가기
Swift

6. 메소드

by 루에 2015. 10. 1.
반응형

메소드(method)


객체의 행위를 클래스에 정의한 함수를 메소드라고한다.

// 메소드의

class Counter {

    var count = 0

    

    func increment() {

        count++

    }

    

    func reset() {

        count = 0

    }

}


let counter = Counter()

counter.increment()

counter.reset()



파라미터 이름


메소드도 파라미터와 파라미터 이름을 사용한다. 클래스 내부에 작성하는 메소드에는 두 번째 파라미터부터 외부 파라미터 이름을 자동으로 사용한다. 별도로 외부 파라미터 이름을 지정하지 않으면 내부 파라미터 이름이 외부 파라미터 이름이 된다.

class Counter2 {

    var count = 0

    

    func incrementBy(amount: Int, numberOfTimes: Int) {

        count += amount * numberOfTimes

    }

    // 번째 파라미터의 외부 파라미터 이름을 생략하도록 선언

    func incrementBy2(amount: Int, _ numberOfTimes: Int) {

        count += amount * numberOfTimes

    }

}


// 번째 파라미터의 외부 파라미터 이름을 반드시 지정해야 한다.

let counter2 = Counter2()

counter2.incrementBy(10, numberOfTimes: 2)

counter2.incrementBy2(10, 2)



self 포인터


클래스 내부에 작성한 메소드가 프로퍼티에 접근하려고 하면 프로퍼티 이름을 사용한다. 만약 메소드의 파라미터 이름과 프로퍼티의 이름이 같으면 프로퍼티에 접근할 수 없다. 이런 경우에는 self를 이용해서 접근한다.

class Counter3 {

    var count = 0

    

    func setCount(count: Int) {

        self.count = count  // self 이용해서 프로퍼티 접근

    }

}



초기화 메소드와 해제 메소드


Swift는 안전한 코드 작성을 요구하는 언어다. 객체의 안전한 사용을 위해서 준비되지 않은 상태의 객체는 사용할 수 없다.


클래스에 선언한 프로퍼티 중에서 옵셔널 타입으로 선언한 프로퍼티는 자동으로 nil로 초기화할 수 있다. 그리고 초기값을 설정하도록 작성한 프로퍼티도 자동으로 설정값으로 초기화할 수 있다.


클래스에 선언한 모든 프로퍼티가 이처럼 별도의 초기화 과정이 필요하지 않다면 클래스에 자동으로 초기화 메소드가 생성된다. 우리의 눈에 보이지 않지만, 객체를 생성하는 과정에서 자동으로 사용된다.

// 별도의 초기화 메소드를 작성할 필요가 없는 클래스

class Rectangle {

    var width = 0

    var height = 0

    var name : String// nil 자동 초기화

}

var obj1 = Rectangle()  // 사용 준비가 완료된다.



초기화 메소드(Initializer)


클래스에 선언한 프로퍼티가 옵셔널 타입이 아니고 초기값을 설정하지 않았으면 객체를 생성하면서 이 프로퍼티의 초기값을 설정하는 초기화 메소드가 필요하다.


초기화 메소드는 func 지시자가 없고 반환값이 없는 init 메소드다.

class Rectangle2 {

    var width : Int

    var height : Int

    

    let ai : Int

    let edges = 0

    

    // 초기화 메소드를 이용해서 프로퍼티 초기화

    init(){

        width = 0

        height = 0

        

        // 상수로 선언한 프로퍼티도 초기화 메소드에서 초기값을 있다.

        ai = 0

    }

}


파라미터를 가지는 초기화 메소드의 사용은 아래와 같다.

class Rectangle3 {

    var width : Int

    var height : Int

    

    // 초기화 메소드를 이용해서 프로퍼티 초기화

    init(width: Int, height: Int){

        self.width = width

        self.height = height

    }

}

// init 메소드는 번째 파라미터부터 외부 파라미터 이름을 사용한다. 생략하고 싶을 경우 언더스코어(_) 사용한다.

var obj2 = Rectangle3(width: 10, height: 10)


// 초기화 메소드를 작성하면 파라미터가 없는 기본 init 메소드가 자동으로 생성되지 않기 때문에 파라미터를 넣지 않을 경우 에러가 발생한다.

var obj3 = Rectangle3()     // error



Designated Initializer


Swift에서 초기값이 설정되지 않은 객체 사용 방지를 위해 지켜야 할 사항이 많다. 클래스에 옵셔널 타입이 아니고 초기값 설정이 안된 프로퍼티가 정의됐다면 반드시 1개 이상의 Designated Initializer가 있어야 한다.


Designated Initializer는 초기화가 필요한 모든 프로퍼티의 초기값을 설정하도록 먼저 작성하고 나머지 초기화 코드를 작성한다.

class MyClass {

    var a : Int

    var b : Int

    

    func prepare() {

        // TO DO

    }

    

    init(a : Int, b : Int) {

        self.a = a


        prepare()   // error

        

        self.b = b

        

        prepare()   // 프로퍼티 초기화 후에는 허용

    }

}



Conveninece Initializer


이 초기화 메소드는 모든 프로퍼티의 초기값을 설정하지 않는다. 그래서 단독으로 객체의 초기화 과정을 완료할 수 없고 다른 초기화 메소드를 이용해서 초기화 과정을 수행한다. 이 과정을 초기화 메소드 위임이라고 한다.


이 초기화 메소드는 앞에 Convenince 를 붙인다.

class MyClass {

    var a : Int

    var b : Int

    

    // Designated Initializer

    init(){

        a = 0

        b = 0

    }

    

    // Convenience Initializer

    convenience init(a: Int) {

        self.init()

        self.a = a

    }

}


var obj3 = MyClass(a: 10)



Failable Initializer


객체를 초기화하는 init 메소드에 return 코드를 작성하지 않지만, init 메소드가 실행되면 초기화 과정을 거친 객체가 반환된다. 객체를 생성하는 과정에서 객체 초기화는 실패할 수도 있다. 예를 들면 사람 객체를 생성하면서 출생연도에 음수를 입력하면 객체가 정상적으로 초기화 될 수 없다.


Failable Initializer는 객체의 초기화가 실패할 수도 있는 경우에 작성하는 메소드로, 초기화가 실패하면 nil을 반환하도록 작성한다.

class Person {

    var birth : Int

    

    init?(birth: Int) {

        

        if birth < 0 {  // 0보다 작은 값이 들어올 경우 nil 반환한다.

            self.birth = 0

            return nil

        }

        self.birth = birth

    }

    

    deinit{

        // 해제 메소드

    }

}


타입 메소드


타입 메소드는 객체를 생성하지 않고 동작하는 메소드다. 메소드를 선언하면서 func 앞에 static 키워드를 이용해서 작성한다.

class MyClass1 {

    var property = 0

    

    static func typeMethod() {

        property = 2    // error. 프로퍼티 접근 불가

    }

    

    func instanceMethod() {

        property = 1    // 인스턴스 메소드에서 접근 가능

    }

}


// call static Method

MyClass1.typeMethod()



타입 프로퍼티


프로퍼티도 타입 형태로 사용할 수 있다.

class Rectangle4 {

    // 계산 타입 프로퍼티

    static var name : String {

        return "rectangle"

    }

    // 저장 타입 프로퍼티

    static var edge = 4

}

// 참조

Rectangle4.name

Rectangle4.edge



프로퍼티 감시


프로퍼티의 값에 변화가 생기면 동작해야 하는 코드. 프로퍼티를 감시하는 감시자는 willSet과 didSet을 이용해 설정한다. 값이 변경되기 전에 willSet이 동작하고 newValue로 새로 대입되는 값을 알 수 있고 변경된 후에는 didSet이 동작하고 oldValue로 변경 이전의 값을 사용할 수 있다.

class Rectangle5 {

    var width = 0

    var height : Int = 0 {

        // 프로퍼티에 값이 설정된 동작

        didSet {

            // 0보다 작으면 0으로 변경

            if height < 0 {

                height = 0

            }

            print("height didSet \(height) - oldValue : \(oldValue)")

        }

    }

}

var rect5 = Rectangle5()

rect5.width = 50

rect5.height = -30

rect5.height    // 0으로 변경됨



늦은 초기화 프로퍼티


저장 프로퍼티에 lazy 키워드를 이용해서 선언하면 해당 프로퍼티를 사용하는 시점에 초기화된다.

class Person3 {

    lazy var phone = 30 // phone 사용될 30으로 초기화

}


// 객체 생성 시점에 초기화 안됨

var person3 = Person3()


// 사용될 초기화

person3.phone















반응형

댓글