Swift/개념 & 응용

[Swift] Swift 문법 - 클래스(Class) (2)

유정주 2021. 8. 26. 00:10
반응형

안녕하세요.

 

오늘은 Swift 문법 - 클래스(Class) (1)에 이어서 클래스에 대해 더 알아보겠습니다.

이전 포스팅은 아래 링크를 클릭하면 바로 볼 수 있습니다.

2021.08.25 - [개발,IT,코딩/iOS, Swift] - [Swift] Swift 문법 - 클래스(Class) (1)

 

그럼 시작하겠습니다.


참고 자료

Apple Swift Document

https://developer.apple.com/documentation/swift

 

해당 포스팅은 Smile Han님의 유튜브 영상을 참고하며 작성하였습니다.

https://www.youtube.com/channel/UCM8wseo6DkA-D7yGlCrcrwA


stored property & computed property

stored property는 지금까지 본 property처럼 직접 특정 값을 할당해서 사용합니다.

Swift에서 property라고 함은 기본적으로 stored property를 의미합니다.

 

computed property는 계산된 값을 할당합니다.

computed property는 getter와 setter라는 것을 정의할 수 있는데요.

computed property에 값을 리턴하는 메서드인 getter는 get을 이용해서 만들고

다른 property의 값을 대입하는 메서드인 sett는 set을 이용해서 만든다.


getter

class Person {
    var name: String //stored property
    var age: Int //stored property
    var koreanAge: Int { //computed property
        get { 
            return age+1 //stored property인 age에서 1을 더한 값을 return함
        }
    }

    func display() { //instance method
        print("\(name) is \(age)")
    }

    func displayInKorea() {
        print("\(name) is \(koreanAge) in Korea")
    }

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    } //designated initializer
}

var jeong = Person(name: "Jeongju", age: 22)
jeong.display()
jeong.displayInKorea() //따로 초기화를 안 해줬음에도 getter에 의해 23이 출력됨
//실행결과
//Jeongju is 22
//Jeongju is 23 in Korea

koreanAge라는 computed property를 선언했습니다.

한국의 만 나이를 나타낸 변수인데요.

getter를 사용해 age에 1을 더한 값을 koreanAge에 할당하겠다는 의미로 작성하였습니다.

결과에서도 의도처럼 초기화한 age값인 22보다 1 큰 23이 출력되는 것을 볼 수 있네요.

 

참고로 setter가 없으면 get은 생략하고 return문만 써줘도 됩니다.

var koreanAge: Int {
        return age+1 
}

setter

class Person {
    var name: String
    var age: Int
    var koreanAge: Int {
        get {
            return age+1
        }

        set(koreanAge) {
            age = koreanAge - 1
        }
    }

    func display() { //instance method
        print("\(name) is \(age)")
    }

    func displayInKorea() {
        print("\(name) is \(koreanAge) in Korea")
    }

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    } //designated initializer
}

var jeong = Person(name: "Jeongju", age: 22)
jeong.koreanAge = 24 //setter 호출
jeong.display() //22로 초기화 했음에도 setter에 의해 23의 값이 출력됨
jeong.displayInKorea()
//실행결과
//Jeongju is 23 
//Jeongju is 24 in Korea

setter는 instance가 koreanAge에 값을 할당할 때 호출됩니다.

 

예시를 보면 jeong instance가 koreanAge에 24를 대입했습니다.

이 타이밍에 setter가 호출되어 age에는 1을 감소시킨 값인 23이 할당됩니다.

그래서 최종 결과에는 23과 24로 출력이 됩니다.

 

Shorthand Setter Declaration

setter에 반드시 매개변수명을 설정해야하는 것은 아닙니다. 

 

setter의 기본 매개변수명은 newValue입니다.

따로 매개변수명을 설정하지 않으면 아래처럼 newValue로 매개변수를 사용 가능합니다.

set {
    age = newValue - 1
}

 

--------------------------------------------------------------------------

 

Method Overloading(생성자 중첩)

객체 지향을 공부해보신 분이라면 익숙한 개념이실겁니다.

method overloading에 의해 Class를 여러 가지 방법으로 생성할 수 있습니다.

 

매개변수의 개수와 자료형이 다른 같은 이름의 함수를 여러 개 정의합니다.

아래 예시는 매개변수가 다른 두 생성자를 통해 두 가지 방법으로 인스턴스를 만들 수 있습니다.

 

init overloading 예시

class Person {
    var name: String = "unknown" //name을 할당하지 않는 생성자가 있으므로 초기화가 필요함
    var age: Int
    
    func display() { //instance method
        print("\(name) is \(age)")
    }

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    } //designated initializer

    init(age: Int) {
        self.age = age
    }
}

var jeong = Person(name: "Jeongju", age: 22)
jeong.display()
var unknown = Person(age: 30)
unknown.display()
//실행결과
//Jeongju is 22
//unknown is 30

만약 여러 생성자 중 하나라도 초기화가 안 된 property가 있다면

초기화가 필요하니 주의해 주세요.


failable initializers

직역하면 실패가 가능한 생성자입니다.

역할도 이름 그대로입니다. 생성자의 옵셔널 버전이죠.

 

예를 들어, 앱을 만들다 보면 argument로 전달한 파일이 없을 때 nil이 들어가서 init()이 실패할 수 있습니다.

이런 상황에서 nil값도 저장할 수 있게 하는 역할입니다.

failable initializer에는 오류 상황에 nil을 리턴하는 조건문이 있습니다.

위의 예시에서는 파일이 존재하는 않는 상황이겠네요.

 

정의 방법은 init 다음에 ?를 붙이면 됩니다. 옵셔널 값이 리턴되도록 하는 것이죠.

옵셔널과 동일하게 값이 존재한다는 확신의 의미인 !를 붙여도 되지만 잘 사용하지는 않습니다.

init?로 만든 인스턴스는 옵셔널로 만들어져서, 사용하려면 !키워드를 이용해 옵셔널을 언래핑 해야 합니다.

 

failable initializer 예시

class Person {
    var name: String
    var age: Int
    
    func display() { //instance method
        print("\(name) is \(age)")
    }

    init?(name: String, age: Int) {
        self.name = name
        if age <= 0 {
            return nil
        } else {
            self.age = age
        }
    } //failable initialize
}

 //옵셔널 값으로 생성 성공. 언래핑하기 위해 마지막에 ! 추가
var jeong = Person(name: "Jeongju", age: 22)!
jeong.display()

//nil이 들어가므로 언래핑하면 crash 된다.
var errorMan = Person(name: "ErrorMan", age: 0)
print(errorMan)
//실행결과
//Jeongju is 22
//nil

 

위처럼 강제 언래핑을 하면 nil일 때 crash가 납니다.

그래서 옵셔널 바인딩 등으로 안전하게 처리하는 게 좋습니다.

 

옵셔널 바인딩 예시 1

var jeong = Person(name: "Jeongju", age: 0)
if let person = jeong {
    person.display()
} else {
    print("Age must be greater than zero.")
}
//실행결과
//Age must be greater than zero.

 

옵셔널 바인딩 예시 2

if let jeong = Person(name: "Jeongju", age: 0) {
    jeong.display()
} else {
    print("Age must be greater than zero.")
}
//실행결과
//Age must be greater than zero.

이렇게 Swift의 클래스에 대해 알아보겠습니다.

훨씬 더 깊은 내용이 많겠지만 처음 배우는 입장이라 간단한 개념까지만 아는 게 좋을 것 같네요.

실제 앱을 배우면서 더 깊게 탐구해봐야겠습니다.

 

감사합니다!


아직은 초보 개발자입니다.

더 효율적인 코드 훈수 환영합니다!

공감 댓글 부탁드립니다.

반응형