Class

Swift는 객체지향언어이니 만큼, 클래스와 객체부분을 공부할 때 눈에 힘이 빡 👀 들어간다. 다행히(?) 자바스크립트에서 익혔던 클래스와 객체 개념과 크게 다르지 않아서 익숙하다.

// init 함수 없이 만들어진 클래스
class Test {
    var age = 100
    var name = "백곤조"
    func exec() {
        print("제 이름은 \(name)이구요 \(age)살이에요")
    }
}

let test = Test()
test.exec()
// 제 이름은 백곤조이구요 100살이에요

test.age = 35
test.exec()
// 제 이름은 백곤조이구요 35살이에요

init과 self

init 함수를 클래스 안에 만들면서 self 키워드를 활용할 수 있다. 자바스크립트나 자바에서 봤던 this와 거의 동일한 역할을 수행하는 것 같다. 물론 init 함수를 사용하면 반드시 self 키워드를 써야하는 것은 아니다. 중요한 것은, init 함수 안에 어떤 함수든 값이든 정의하느냐에 따라, 이 클래스의 인스턴스가 인스턴스 선언만으로 init 함수의 내용을 실행할 수 있는지 여부가 결정된다. 쉽게 말하자면, 클래스 안에 init 함수를 선언하지 않는다면 클래스의 인스턴스는 클래스 내부에 정의된 다른 함수들을 메소드로써 따로 선언(인스턴스.함수())해야 한다.

// init 함수에 self 키워드를 쓰지 않고 만들어진 클래스
class Test {
    var age = 99
    var name = "청곤조"
    func exec() {
        print("제 이름은 \(name)이구요 \(age)살이에요")
    }
    init() {
        exec()
    }
}

let test = Test()
// 제 이름은 청곤조이구요 99살이에요

test.age = 64
test.name = "58년개띠"
test.exec()
// 제 이름은 청곤조이구요 99살이에요
// 제 이름은 58년개띠이구요 64살이에요

init 함수 안에 self 키워드를 사용한다면, 인스턴스는 이제 이 init 함수의 매개변수를 토대로 선언되어야 제대로 활용될 수 있게 된다.

// init 함수에 self 키워드를 사용하여 만들어진 클래스
class Test {
    var age : Int
    var name : String
    func exec() {
        print("제 이름은 \(name)이구요 \(age)살이에요")
    }
    init(age: Int, name: String) {
        self.age = age
        self.name = name
    }
}

let test = Test(age: 20, name: "흑곤조")
test.exec()
// 제 이름은 흑곤조이구요 20살이에요

상속

어떤 클래스의 내용을 본따서 새로운 클래스를 만들 수 있다. 이때 두 클래스는 부모-자식 관계로 정의할 수 있다.

class Test {
    var age = 100
    var name = "백곤조"
    func exec() {
        print("제 이름은 \(name)이구요 \(age)살이에요")
    }
    init() {
        exec()
    }
}

class Test1 : Test {
    // blank
}

let test1 = Test1()
// 제 이름은 곤조맨이구요 100살이에요

또한, override를 통해 부모 클래스의 함수에 대해 원하는 내용으로 덮어쓸 수 있다.

class Test {
    var age = 100
    var name = "백곤조"
    func exec() {
        print("제 이름은 \(name)이구요 \(age)살이에요")
    }
    init() {
        exec()
    }
}

class Test1 : Test {
    override func exec() {
        print("이것은 자식 클래스다")
    }
}

let test1 = Test1()
test1.exec()
// 이것은 자식 클래스다
// 이것은 자식 클래스다

당연히 자식 클래스는 그 안에 변수 선언이 없더라도 부모 클래스에서 이미 선언된 변수들을 언제든지 바로 쓸 수 있으며, 여기에 새로운 변수를 추가해서 사용하는 것도 가능하다.

class Test {
    var age = 100
    var name = "백곤조"
    func exec() {
        print("제 이름은 \(name)이구요 \(age)살이에요")
    }
    init() {
        exec()
    }
}

class Test1 : Test {
    var address = "서울"
    override func exec() {
        print("저는 \(address)사는 \(name)이구요 \(age)살이에요")
    }
}

let test1 = Test1()
// 저는 서울사는 백곤조이구요 100살이에요

get & set

클래스 안에서 get과 set 구문을 통해 보다 더 유연하게 값을 변경할 수 있다. 아래의 코드는 주어진 age 변수에 변화가 없기 때문에 newAge 변수에는 바로 2 * age 값이 대입된다.

// get, set 구문을 사용했지만 아직 활용 안한 경우
class Test {
    var age = 50
    var newAge : Int {
        get {
            return 2 * age
        }
        set {
            age = newValue * 10
        }
    }
    
    func exec() {
        print("저는 \(age)살이에요")
        print("저는 \(newAge)살이에요")
    }
}

let test = Test()
test.exec()
// 저는 50살이에요
// 저는 100살이에요

반면에, test 인스턴스가 newAge에 대한 새로운 get & set을 명시하게 되면 결과는 아래와 같이 달라진다.

class Test {
    var age = 50
    var newAge : Int {
        get {
            return 2 * age
        }
        set {
            age = newValue * 10
        }
    }
    
    func exec() {
        print("저는 \(age)살이에요")
        print("저는 \(newAge)살이에요")
    }
}

let test = Test()
test.newAge = 2
test.exec()
// 저는 20살이에요
// 저는 40살이에요

이 코드가 작동된 원리는 test.newAge = 2에 의해 set 구문이 실행된 것에서 시작한다. 즉, age = 2 * 10가 되었으며, 따라서 이에 따라 get 구문이 실행되어 newAge 변수는 2 * (2 * 10)이 실행된 결과를 리턴받게 된다.

profile
전직 시스템엔지니어, 현직 데이터엔지니어, 하지만 하고 싶은건 iOS 개발

0개의 댓글