궁금한 내용을 검색해보세요!
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
서근 개발노트
티스토리에 팔로잉
SWIFT/Grammar

Swift : 기초문법 [프로퍼티#1 - 저장 프로퍼티]

서근
QUOTE THE DAY

-
Written by SeogunSEOGUN

반응형

프로퍼티

프로퍼티란 클래스, 구조체, 열거형에서 소속된 변수 및 속성 등을 불리는 개념

메서드는 특정 타입에 관련된 함수

 

변수나 상수, 함수 언제 어느 목적에 사용되는지에 따라 용어가 프로퍼티 또는 메서드로 불린다.

프로퍼티 종류

TIP
 
 

프로퍼티 종류
➜ 저장 프로퍼티 Stored Property
➜ 연산 프로퍼티 Computed Property
➜ 타입 프로퍼티 Type Property
➜ 프로퍼티 감시자 Property Observers

Stored Property 저장 프로퍼티

  • 인스턴트의 변수나 상수를 의미
  • 구조체와 클래스에서만 사용 가능
  • 저장 프로퍼티는 사용 시점에 따라서 Lazy Stored Property(지연 저장 프로퍼티)라는 것도 있음
  • 특정 타입의 인스턴스에 사용되는 것을 뜻함

Computed Property 연산 프로퍼티

  • 클래스, 구조체, 열거형에서 사용 가능
  • var로 선언해야 함
  • 클래스, 구조체, 열거형에 값을 저장할 저장 프로퍼티가 반드시 하나 있어야 함
  • get, set을 동시에 구현 가능하고, 읽기 전용으로 get만 구현 가능
  • set의 매개변수를 생략한다면 반드시 newValue 키워드를 사용해야 함
  • 직접적인 값을 저장하지 않고 값을 연산한 결괏값
  • 특정 타입의 인스턴스에 사용되는 것을 뜻함

Type Property 타입 프로퍼티

  • 특정 타입에 사용되는 프로퍼티 (클래스 변수)

Property Observers 프로퍼티 옵저버(감시자)

  • 프로퍼티 옵저버는 값이 변경되면 작업을 취할 수 있음. 
  • 프로퍼티 값이 변경될 때마다 호출. 변경되는 값이 현재 값과 같더라도 호출됨
  • 상속받은 저장 프로퍼티 또는 연산 프로퍼티에도 적용됨
  • 상속받지 않은 연산 프로퍼티에는 사용 불가(사용할 필요도 없음) : gettersetter을 통해 감시자를 구현할 수 있기 때문
  • willSet : 값이 변경되기 직전에 호출하는 메서드
  • didSet : 메서드와 프로퍼티 값이 변경된 직후에 호출하는 메서드

저장 프로퍼티

클래스 혹은 구조체의 인스턴스와 연관된 값을 저장하는 기본적인 프로퍼티.

변수 상수 키워드에 따라 [ var변수 저장 프로퍼티  /  let상수 저장 프로퍼티 ]

 

기본값 및 초깃값 지정 가능함

 

구조체 - 저장 프로퍼티가 옵셔널이 아니어도 이니셜라이저를 자동 생성함

클래스 - 옵셔널이 아니면 기본값을 지정해주거나 이니셜라이저를 통해 반드시 초기화 해줘야함

 

 

Struct

struct Information {
    var age: Int  //저장 프로퍼티
    var country: String  //저장 프로퍼티
}

//구조체에는 기본적으로 저장프로퍼티 매개변수를 갖는 이니셜라이저가 있음
let PersonalInfo: Information = Information(age: 10, country: "한국")

Class

class Position {
    
    var point: CoordinatePoint //변수 저장 프로퍼티
    let name: String //상수 저장 프로퍼티
    
    // 프로퍼티 기본값이 없으면 이니셜라이저를 정의해야함
    init(name: String, point: CoordinatePoint) {
        self.name = name
        self.point = point
    }
}
//사용자 정의 이니셜라이저를 사용해야 초깃값을 할당 할 수 있음
let SeogunPosition: Position = Position(name: "서근", point: PersonalPoint)

위에서 구조체는 기본적인 이니셜 라이저를 자동으로 제공하지만 클래스는 사용자 정의 이니셜라이저를 지정하거나 초깃값을 설정해야 한다고 했는데, 그렇다면 초깃값은 어떻게 설정할까?

 

번거롭지만 클래스의 저장 프로퍼티 초깃값을 지정해주면 위처럼 사용자정의 이니셜라이저를 구현할 필요가 없다.

 

Struct

struct CoorrdinatePoint {
    var x = 0 // 저장 프로퍼티
    var y = 300  //저장 프로퍼티
}

//프로퍼티에 기본값을 할당했기 때문에 전달인자로 초깃값을 넘길 필요 없음
let PersonalPoint1: CoorrdinatePoint = CoorrdinatePoint()
//기존에 초깃값을 할당할 수 있는 이니셜라이저도 그대로 사용가능
let PersonalPoint2: CoorrdinatePoint = CoorrdinatePoint(x: 10, y: 200)

print("서근 위치 x: \(PersonalPoint1.x) y: \(PersonalPoint1.y)")
//서근 위치 x: 0 y: 300

Class

class Position {
    var point: CoorrdinatePoint = CoorrdinatePoint() //변수 저장 프로퍼티
    var name: String = "Unknown" //상수 저장 프로퍼티
}

//초깃값을 설정해줬다면 사용자 정의 이니셜라이저를 사용할 필요 없음
let SeogunInfo: Position = Position()
SeogunInfo.name = "서근"
SeogunInfo.point = PersonalPoint1

print("이름: \(SeogunInfo.name), 위치 x: \(SeogunInfo.point.x) y: \(SeogunInfo.point.y)")
//이름: 서근, 위치 x: 0 y: 300

초깃값을 사용해서 간단해지긴 했는데, 인스턴스 생성 후 항상 일일이 값을 전달해줘야 한다. 또, name 같은 경우 상수 let으로 변경하지 못하게 해주고 싶지만 초깃값을 지정하면 그렇게 할 수 도 없다. 

 

인스턴스를 생성할 때 초깃값을 보내는 이유는 옵셔널이 아니라 값으로 선언되었기 때문. 

 

하지만 초깃값을 넣지 않아도 되는 옵셔널 타입이라면?  꼭 값을 할당하지 않아도 됨.

struct CoordinatePoint {
    
    //위치는 필수이기 때문에 옵셔널 타입 X
    var x: Int  //저장 프로퍼티
    var y: Int  //저장 프로퍼티
}

class Position {
    // 현재 사람의 위치를 모르기 때문에 옵셔널 타입으로 설정
    var point: CoordinatePoint?
    let name: String
    
    init(name: String) {
        self.name = name
    }
}

// point는 옵셔널 타입이기 때문에 필수가 아님. 하지만 name은 상수이기 때문에 필수
let SeogunPosition: Position = Position(name: "서근")
print("\(SeogunPosition.name)") //서근

// 위치를 알게 된다면 그 때 위치 값을 할당할 수 있다.
SeogunPosition.point = CoordinatePoint(x: 30, y: 100)

이렇게 옵셔널과 이니셜라이저를 적절히 사용 가능하다.

지연 저장 프로퍼티  Lazy Stored Property

저장 프로퍼티는 인스턴스 생성 시 프로퍼티 값이 없으면 옵셔널로 선언 가능. 

지연 저장 프로퍼티는 필요할 때 값을 할당하는 프로퍼티이며, 호출이 있어야 값 초기화 가능.

 

주의할 점은 var 변수에만 사용 가능하다. let 상수는 인스턴스가 완전히 생성되기 전에 초기화해야 하므로 필요할 때 값을 할당하는 지연 저장 프로퍼티와 맞지 않음.

 

주로 클래스나 구조체에 많이 사용된다. 

 

lazy 키워드를 이용해 사용하며 클래스는 호출했으나 클래스 안 구조체의 값이 할당되기 전에 생성하고 싶다면 사용하면 된다.

struct CoordinatePoint {
    var x: Int = 0
    var y: Int = 200
}

let SeogunPount: CoordinatePoint = CoordinatePoint(x: 10, y: 20)

class Position {
    lazy var point: CoordinatePoint = CoordinatePoint()
    let name: String
    
    init(name: String) {
        self.name = name
    }
}
//lazy 키워드 덕분에 point 프로퍼티를 사용하지 않아 Point객체가 생성되지 않음
let SeogunPositon: Position = Position(name: "서근")

위 코드에서 Point 프로퍼티를 사용하지 않았기 때문에 불필요한 성능 저하나 공간 낭비를 줄일 수 있다.

TIP
 
 

다중 스레드와 지연 저장 프로퍼티
다중 스레트 환경에서 생성되지 않은 지연 저장 프로퍼티에 많은 스레드가 비슷한 시점에서 접근한다면 여러 번 초기화가 될 수 있다.

 

읽어주셔서 감사합니다🤟

 

 


잘못된 내용이 있으면 언제든 피드백 부탁드립니다.


서근


위처럼 이미지 와 함께 댓글을 작성할 수 있습니다.