[Swift] Property, Method

Lena·2020년 11월 23일

Properties

Stored Properties

var, let 키워드로 변수나 상수 값을 저장할 수 있는 프로퍼티를 stored property라고 한다.

struct FixedLengthRange {
    var firstValue: Int
    let length: Int
}

var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
rangeOfThreeItems.firstValue = 6
rangeOfThreeItems.length = 5 // error, length is let

let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
rangeOfFourItems.firstValue = 6 // error, rangeOfFourItems is let

상수에 저장한 구조체 인스턴스는 생성 이후 프로퍼티 값을 변경할 수 없다.
이는 구조체가 value type이기 때문이고, reference type인 class와 다른 부분이다.

The same is not true for classes, which are reference types. If you assign an instance of a reference type to a constant, you can still change that instance’s variable properties.

class FixedLengthRange {
    var firstValue: Int = 0
    let length: Int = 3
}

var rangeOfThreeItems = FixedLengthRange()
rangeOfThreeItems.firstValue = 6
rangeOfThreeItems.length = 4 //error, lenth is let

let rangeOfThreeItems = FixedLengthRange()
rangeOfThreeItems.firstValue = 6 // it's ok
rangeOfThreeItems.length = 4 //error, lenth is let

Lazy Stored Properties

  • var와 함께 사용되고, 실제 값이 사용되기 전까지 초기화를 지연시키는 것이다.
  • let은 초기값이 반드시 존재해야 하기 때문에 lazy를 사용할 수 없다.
  • 또한, lazy는 처음 사용될 때 값을 메모리에 올리고, 이후에는 그 값을 사용하기 때문에 computed property에는 사용할 수 없다.
/* lazy (초기화 지연) */
@IBOutlet private var cardButtons: [UIButton]!

var game: Concentration = Concentration(numberOfPairsOfCards: cardButtons.count/2) // error
// Cannot use instance member 'cardButtons' within property initializer; property initializers run before 'self' is available
// 프로퍼티 이니셜라이저가 self가 가능하기 전에 실행된다.

// cardButtons가 초기화 완료되고 나서, game에 접근할 때 초기화를 진행한다.
lazy var game: Concentration = Concentration(numberOfPairsOfCards: cardButtons.count/2)

Computed Properties

stored property와는 다르게 값를 저장하지 않고, getter와 setter(optional)를 제공한다.
let은 값이 변경될 수 없기 때문에 computed property 앞에 올 수 없다.

var center: Point { // let 불가
    get {
        let centerX = origin.x + (size.width / 2)
        let centerY = origin.y + (size.height / 2)
        return Point(x: centerX, y: centerY) // return 생략 가능
    }
    set(newCenter) { // newCenter 생략 가능, 'newValue' is used as a default
        origin.x = newCenter.x - (size.width / 2)
        origin.y = newCenter.y - (size.height / 2)
    }
}
    
// type extension 으로 자주 사용된다.
extension Int { //Int형 확장
    var arc4random: Int { // read-only, 'get' 생략 가능
        return Int(arc4random_uniform(UInt32(self))) // 0 ~ (self-1) 사이의 난수
    }
}

Property Observers

property observer는 didSet, willSet 키워드와 함께 쓰이며, 프로퍼티의 값이 변경될 때마다 called 된다.
willSet은 값이 변경되기 직전에, didSet은 값이 변경된 직후 호출된다.

    @IBOutlet weak var emojiCollectionView: UICollectionView! {
        didSet {
            emojiCollectionView.dataSource = self
            emojiCollectionView.delegate = self
        }
    }

Type Properties

  • static이나 class 키워드가 붙은 프로퍼티를 의미한다.
  • class는 override 가능하고, static은 불가능하다.
  • 인스턴스 생성 없이 Type.property로 접근 가능하다.
  • 프로퍼티에 접근할 때 한 번 lazy initialize 하기 때문에 lazy가 필요 없다.
class SomeClass {
    var storedInstanceProperty = "Instace value"
    
    static var storedTypeProperty = "Type value"
    
    static var computedTypeProperty: Int {
        return 27
    }
    
    class var overrideableComputedTypeProperty: Int {
        return 107
    }
}

class someSubClass: SomeClass {
    override static var storedInstanceProperty = "Instace value" // error: cannot override stored property
    
    override static var computedTypeProperty: Int { // error: cannot override static property
        return 30
    }
    
    override class var overrideableComputedTypeProperty: Int {
        return 1
    }
}

Methods

Instance Methods

  • struct, enum과 같은 value type의 인스턴스 메서드는 그 안에서 property 값을 변경할 수 없다.
  • value type의 프로퍼티 값을 변경하는 것은 원본 변경을 의미하므로 기본적으로는 불가능하다.
struct Point {
    var x = 0
    var y = 0
    
    mutating func moveBy(x deltaX: Double, y deltaY: Double) { // mutating 키워드가 없으면 error
        x += deltaX
        y += deltaY
    }
}

Type Methods

  • static이나 class 키워드가 붙은 메서드를 의미한다.
  • class는 override 가능하고, static은 불가능하다.
  • 인스턴스 생성 없이 Type.property로 접근 가능하다.
class SomeClass {
    static func someTypeMethod() {
        // type method implementation goes here
    }
    class func overrideableTypeMethod() {
        // type method implementation goes here
    }
}

SomeClass.someTypeMethod()

class someSubClass: SomeClass {
    override static func someTypeMethod() { } // error, cannot override static func
    override class func overrideableTypeMethod() {
        // override here
    }
}

References

https://docs.swift.org/swift-book/LanguageGuide/Properties.html
https://docs.swift.org/swift-book/LanguageGuide/Methods.html

0개의 댓글