Dog foot print

[SWIFT] 프로퍼티 본문

IOS/Swift

[SWIFT] 프로퍼티

개 발자국 2021. 7. 13. 18:06

프로퍼티

객체에는 propertymethod 두개로 이루어져있습니다. 스위프트에서는 프로퍼티의 기능과 종류가 많아 메서드와 비슷해 보입니다.

property의 주목적은 “값을 저장하고, 값을 전달한다. “ method의 주목적은 단순히 함수이다. 정도로 생각하면 편할 듯 합니다 .

저장 프로퍼티

class Circle {
    var width = 0.0;
    var height = 0.0;
    let pie = 3.141592; //변경 불가능
    var name : String; //인스턴스 생성까지 할당해야함 
    let id : String; // 인스턴스 생성까지 할당해야한다.
    var backgroundColor : String?; //추후 초기화 가능
      var className : String!; // 추후 할당후 사용 가능  

    init(name : String, id : String) {
        self.name = name;
        self.id = border
    }
}
let myCircle = Circle("my");

저장 프로퍼티는 클래스내부에 var혹은 let으로 작성된 변수들을 의미합니다. 이 저장 프로퍼티는 다음과 같은 조건을 가집니다.

  • 초기화 이전까지 값이 할당 되지 않으면 미리 값을 할당해야한다.
  • let으로 작성된 멤버가 값이 할당 되어 있지 않으면, 인스턴스화 되기 전까지 할당 되어야 한다.
  • let으로 작성된 멤버가 값이 할당되어 있으면 init 구문에서도 재할당 할 수 없다.
  • 옵셔널로 지정되어있는 변수는 init구문에서 초기화하지 않고 차후 사용직전에 초기화 할 수 있다.
  • let으로 작성되어 있는 변수는 선언 구문 외부에서 변경 할 수 없다.
  • 묵시적 옵셔널 해제 타입을 사용하여, 초기화하지 않은 구문에서 에러를 발생시키지 않을 수 있다.

지연 저장 프로퍼티

지연 저장 프로퍼티는 해당 프로퍼티를 사용하기 전까지는 값의 형태로 구현하지 않는 프로퍼티를 의미합니다. 이 구문은 변/상수 타입 왼쪽에 lazy라는 예약어를 사용하여, 구현 할 수 있습니다.

import UIKit;

class Circle {
    var width = 1.0;
    var height = 1.0
    lazy var lazyTest = LazyTest();

    init() {
        print("Circle 초기화 !")
    }
}


class LazyTest{
    init(){
        print("LazyTest 초기화 !")
    }
}

let myCircle = Circle(); //Circle 초기화

myCircle.lazyTest //LazyTest 초기화 

클로저를 이용한 프로퍼티 초기화

클로저를 이용하여 프로퍼티를 초기화 할 수 있습니다. 이 말인 즉슨, 값을 초기화 할 때, 특정 값을 init 을 사용하지 않고 로직을 따로 구현하여 원하는 값을 도출 할 수 있게 됩니다.

import UIKit;

class Circle {
    var width = 1.0;
    var height = 1.0

    let backgroundColor = {() -> String in
        print("background");
        return "black"
    }()

    let id : String;
    lazy var name = { (_ id : String) -> String in
        print("클로저를 이용한 name이 생성되었습니다.")
        return "\(id)-Circle";
    }(self.id)

    init(id : String) {
        self.id = id;
    }
}

let myCircle = Circle(id : "id"); //background출력

myCircle.name //클로저를 이용한 name이 생성되었습니다.출력

Name 프로퍼티는 클로저를 활용하였지만 변수타입에 lazy가 붙어있습니다. 이는 id를 파라메터로 전달 받기 위해서는 init 메서드가 실행이 되어야 id값이 할당 되기 때문에 사용 되었습니다.

연산 프로퍼티

연산프로퍼티는 값을 호출하거나, 저장할 때 마다 로직을 통과 하여, 새로운 값을 전달 해줄 수 있습니다. 이 프로퍼티는 setget으로 이루어지며, 만약 set메서드가 존재하지 않는다면 이 프로퍼티는 읽기 전용 프로퍼티 가 되어 외부에서 값을 할당 할 수가 없습니다.

class UserInfo{

    let birth : Int;

    var thisYear : Int! {
        get {
            let df = DateFormatter();
            df.dateFormat = "yyyy";
            return Int(df.string(from: Date()))
        }
    }

    var age : Int {
        get {
            return (self.thisYear - self.birth) + 1;
        }
    }

    init(birth : Int){
        self.birth = birth;
    }
}

let info = UserInfo(birth: 1994);
info.age; // 28
info.thisYear; // 2021

set메서드는 실제로 연산프로퍼티를 변경하는 것이 아니라, 해당 프로퍼티와 연관되어 있는 값들을 변경하는 용도로 사용된다.

class Rect{
    var originX : Double = 0.0, originY : Double = 0.0;

    var sizeWidth : Double = 0.0, sizeHeight : Double = 0.0;

    var centerX : Double{
        get {
            return self.originX + (self.sizeWidth / 2)
        }
        set(newCenterX){
            originX = newCenterX - (self.sizeWidth / 2)
        }
    }
    var centerY : Double{
        get {
            return self.originY + (self.sizeHeight / 2)
        }
        set(newCenterY){
            originY = newCenterY - (self.sizeHeight / 2)
        }
    }
}

Tip : 읽기 전용 메서드인 경우, get예약어를 제거하고 사용 할 수 있다. closure와 매우 유사하니 조심해야 한다.

class UserInfo{

    let birth : Int;

    var thisYear : Int! {
            let df = DateFormatter();
            df.dateFormat = "yyyy";
            return Int(df.string(from: Date()))
    }

    var age : Int {
            return (self.thisYear - self.birth) + 1;
    }

    init(birth : Int){
        self.birth = birth;
    }
}

옵저버 프로퍼티

옵저버 프로퍼티는 특정 값이 변경 될 때, 변경 전 로직변경 후 로직 을 실행 할 수 있는 특징을 가지고 있다. 연산프로퍼티의 set과 비슷한 역할을 하지만 , 연산프로퍼티는 변경 이전의 값을 set 내부에서 확인하여 로직을 수행 할 수가 없다.

import UIKit;

class UserInfo{

    var name : String = "jh" {
        willSet (newName){
            print("변경된 이름은 \(newName) 이며, 이전 값은 \(name)입니다.")
        }

        didSet(oldName){
            print("변경된 이름은 \(name) 이며, 이전 값은 \(oldName)입니다.")
        }

    }
}

var myInfo = UserInfo();

print(myInfo.name); // "jh"

myInfo.name = "leejongho"

//변경된 이름은 leejongho 이며, 이전 값은 jh입니다.
//변경된 이름은 leejongho 이며, 이전 값은 jh입니다.

Tip : willSet혹은 didSet 하나만 사용 할 수 도 있다.
Tip : 파라메터를 제거하고 예약어인 newValueoldValuewillSetdidSet에서 사용 가능하다.

    var name : String = "jh" {
        willSet{
            print("변경된 이름은 \(newValue) 이며, 이전 값은 \(name)입니다.")
        }

        didSet{
            print("변경된 이름은 \(name) 이며, 이전 값은 \(oldValue)입니다.")
        }
    }

타입 프로퍼티

타입 프로퍼티는 다른 언어에서는 정적 프로퍼티라고 불리우며, Static method라 불립니다. 이 프로퍼티는 인스턴스간 공유하고 있는 값이기 때문에 한곳에서 변경이 되면 모든 인스턴스에서 이 값이 변경됩니다. 주로 모든 인스턴스들이 공유해야 하는 값이나, 외부에서 필요한 참조 값을 지정할 때 사용됩니다.

import UIKit;

class University{
    static var president = "kim" //변경 가능한 타입 저장 프로퍼티
    static let yearOfEstablishment = 1927; //변경 불가능한 타입 저장 프로퍼티

    static var age : Int {
        get{
            let formatter = DateFormatter();
            formatter.dateFormat = "yyyy";
            return (Int(formatter.string(from: Date()))! - yearOfEstablishment + 1);
        }//타입 연산 프로퍼티
    }
}

Tip : 타입 프로퍼티를 정의 할때는 static을 사용하기도 하지만 class let/var를 사용하기도 합니다.

Tip : 타입 연산 프로퍼티의 단축문법이나, set 구문을 동일하게 사용 할 수 있습니다.

#swift

반응형

'IOS > Swift' 카테고리의 다른 글

[SWIFT] 상속  (0) 2021.07.15
[SWIFT] 메서드  (0) 2021.07.13
[SWIFT] 구조체와 클래스  (0) 2021.07.13
[SWIFT] CLOSURE  (0) 2021.07.09
[Swift] Inout  (0) 2021.07.08
Comments