Swift 기초문법

Swift: 프로퍼티(property)

zoonee 2022. 3. 18. 00:54

 

프로퍼티(property) : 클래스, 구조체 또는 열거형 등에 관련된 값을 뜻한다.

 

  • 저장프로퍼티 : 인스턴스의 변수 또는 상수를 의미
  • 연산프로퍼티 : 값을 저장하는게 아니라 특정연산을 실행하는 결과값
  • 타입프로퍼티 : 특정인스턴스에서 사용되는게 아닌 특정타입에서 사용되는 프로퍼티

 

 

저장프로퍼티는 프로퍼티를 사용하는 가장 간단한 방법이다. 변수나 상수로 선언된 클래스나 구조체의 인스턴스의 일부분으로 저장되는 것이다. 강아지라는 구조체를 하나 선언해보았다. 그리고, string타입을 갖는 변수 네임과 string타입을 갖는 상수를 구조체에 선언해보자.

 

struct Dog 라는 구조체를 정의하고, 블록안에 name이라는 변수와 gender라는 상수를 String값을 가지도록 선언해주었다. 이렇게 구조체 내에 선언된 변수나 상수를 저장 프로퍼티라고 한다. 그리고 이 구조체를 인스턴스화 해보자. 변수 dog를 선언해주고, Dog구조체를 인스턴스 해주는데 name에는 "gunter"를 gender에는 "Male"을 대입시켜주었다. 그리고 Dog인스턴스의 값을 확인하기 위해 print함수를 선언해 출력해보자. 실행해보면 dog라는 인스턴스에 name과 gender에 값이 들어가있는걸 확인 할 수 있다. 이렇게 인스턴스에 프로퍼티 값이 저장되어있는걸 저장프로퍼티라고 한다.

 

저장프로퍼티의 값을 변경도 해보자.

→ 프로퍼티 값을 접근해볼텐데 .(점)을 이용하여 접근하여 name에는 "권태완" gender에는 female로 변경하여 실행해보면 상수로 선언된 프로퍼티 gender에서 상수로 선언된 프로퍼티기에 수정할수 없다는 오류가 발생한다.

 

 

→ 그러면 상수로 선언된 구조체 인스턴스의 저장된 프로퍼티는 어떨지 확인해보자. 상수로 dog2를 선언하고 Dog 구조체를 넣어 인스턴스화 하고, 초기값으로는 name에는 "gunter", gender에는 "male"을 적어주자. 

 

그리고, dog2상수도 접근하여 .name의 프로퍼티값을 "권태완"으로 변경하면 바로 에러가 발생한다. 이 경우 name이라는 프로퍼티가 변수로 선언되어 있어도, 구조체 인스턴스인 dog2를 상수로 선언했기에 값을 변경할수 없고 이러한 결과가 나온 이유는 구조체가 Value 값타입이기 때문이다. 구조체 인스턴스를 상수로 선언하면 내부프로퍼티들도 모두 상수로 변경되어 수정을 할 수 없게 된다.

 

 

 

→ 이번에는 class를 확인해보자. Cat이라는 이름의 class를 정의해주자. 블록을 열어 name이라는 변수와 gender라는 상수를 선언하여 두개 모두 String 타입을 주었다. var namelet gender역시 저장형 프로퍼티 이다. 그리고 init 생성자를 만들어줘서 인스턴스가 생성일때 name과 gender프로퍼티가 초기값을 저장하게 하자. name과 gender를 String으로 받고, name은 전달받은 name매개변수로 초기화되게, gender는 전달받은 gender매개변수로 초기화 되게 정의를 해주자.

 

그리고, cat이라는 상수를 선언하여 Cat이라는 인스턴스를 선언하여 초기값으로 name에는 "json", gender에는 "male"이란 값을 대입하고, cat.name에 접근하여 프로퍼티값을 "gunter"로 변경하고 print함수를 통해 cat.name을 출력해보자.

 

cat 인스턴스의 name이라는 프로퍼티가 gunter라고 출력된걸 확인 할 수 있고, 이렇게 구조체는 Value타입이기에 상수로 선언하게 되면은 변수로 선언된 프로퍼티라도 값이 변경이 안되고, class는 참조타입이기 때문에 상수를 선언해도 프로퍼티의 값이 변경된다. 물론 상수로 선언된 gender프로퍼티는 값을 변경할 수 없다.

 


 

 

계산프로퍼티에 대해 알아보자.

 

저장프로퍼티는 구조체나 클래스에만 사용 가능했지만 계산프로퍼티는 class, 구조체, 열거형에서도 사용이 가능하다. 계산프로퍼티는 직접적으로 값을 저장하지 않는 대신에 getter 와 setter를 사용하여 다른프로퍼티와 값들을 직접적으로 접근할 수 있다.

 

Stock이라는 구조체를 정의한 후 블록을 열어 평균단가를 뜻하는 IntaveragePrice 저장형 프로퍼티를 선언하고, 수량을 뜻하는 Int형 quantity저장형 프로퍼티를 선언하고, 매입 가격을 뜻하는 IntpurchasePrice 프로퍼티를 선언한다. 이제 이걸 계산형프로퍼티로 선언해보자. purchasePrice 변수 타입 뒤에 중괄호 코드블록을 만들어 get 키워드 작성하고 { 중괄호 열고 매입가격을 구하는 공식인 평균단가 * 주식수량을 return되게 만들고, 중괄호를 닫는다. 이렇게 되면 Stock 인스턴스를 생성하고, purchasePrice에 값을 가져오게 되면 매입가격을 구하는 공식으로 연산된 매입금액을 받아 올 수 있다. 그리고 set을 선언하고 소괄호 ( ) 안에 원하는 매개변수를 적으면 되고, 새로운 값이 설정되면 매개변수로 전달되게 된다.

 

그리고 나서 purchasePrice의 값이 변경되면 변경된 총 매입금액과 주식수량을 나눠서 저장프로퍼티인 평균단가인 averagePrice를 저장되게 만들어 준다. 매개변수의 이름은 newPrice라고 할 것이고, averagePrice에 변경된 총매입금액(newPrice)과 quantity(주식수량)을 나눠가지고 평균단가가 얼만지 계산해서 저장하도록 하였다. 이렇게 getter, setter를 통해서 값을 연산하고 property에 전달해주는것이 연산형 프로퍼티이다.

 


 

stock 인스턴스를 만들고, 연산프로퍼티에 대해 알아보자.

 

stock이라는 변수를 선언해주고, Stock이라는 인스턴스를 생성하여 평균단가에는 2300원을, 주식수량에는 3을 넣어 3주로 설정해보자. 그리고 stock 인스턴스에 어떤값이 있는지 print를 통해 출력을 해보면 저장프로퍼티 평단가에는 2300원, 수량에는 3이 설정되어있단걸 확인 할 수 있다. 이때 연산형 프로퍼티 purchasePrice의 값을 3000원으로 변경하고, 평균단가가 변경되어 있는지 확인하고 실행을 해보면 평균단가가 2300원에서 1000원으로 변경된걸로 볼 수 있다. 

 

이것도 get과 마찬가지로 평균단가의 값이 변경되면 set안에 있는 코드블록이 실행되고, 변경된 매입가와 총수량을 나눈값이 averagePrice(평균단가) 프로퍼티에 저장되어 평균단가가 1000원으로 변경된다. 이렇게 연산프로퍼티는 인스턴스 내외부에 값을 내보내서 적절한값을 돌려주는 접근자 역할이나 내부의 프로퍼티값을 간접적으로 설정하는 설정자역할을 할 수 있다. 참고로 연산프로퍼티에서 set을 지우고 get만 구해서 읽기전용프로퍼티로도 만들 수 있다. 이렇게 되면 연산프로퍼티는 읽기전용프로퍼티가 되어 값을 변경할 수 없게 된다. 그리고 set을 사용할때 매개변수의 이름을 설정하지 않으면 디폴트값이 newValue라는 이름으로 사용할 수 있다. 

 

 


 

 

프로퍼티 옵저버에 대해 알아보자.

 

프로퍼티 옵저버는 프로퍼티의 값에 변화를 관찰하고 반응한다. 새로운값과 기존값이 똑같더라도 프로퍼티옵저버는 호출이 되는데, 프로퍼티가 set될때마다 호출된다고 생각하면 된다. 프로퍼티 옵저버는 3가지 경우에만 사용 가능하다. 저장프로퍼티랑 오버라이딩된 저장,계산프로퍼티에서만 사용 가능하다.

 

→ Account라는 클래스를 정의하고 블록을 열어 잔액을 뜻하는 credit이라는 변수를 선언하고 Int타입을 주고, 값을 0을 준 저장형프로퍼티를 선언하였다. 그리고 블록을 연다음 willSet과 didSet을 선언하였다. 프로퍼티의 옵저버에는 두가지가 있다. 값이 저장되기 직전에 호출되는 willSet옵저버, 값이 저장된 직후에 호출되는 didSet옵저버. 

 

willSet옵저버는 새로 저장된 프로퍼티의 값을 상수 매개변수로 전달하고, 이 매개변수의 이름을 willSet 구문안에 사용할 수 있도록 이름을 지정할 수 있고, 만일 지정하지 않는다면 기본값인 newValue가 매개변수의 이름이 된다. didSet옵저버는 프로퍼티의 기존값이 상수 매개변수로 전달되어진다. 이 매개변수에 이름은 didSet구문안에 사용할 수 있도록 이름을 지정할 수 있고, 만약 지정하지 않으면 기본값이 oldValue가 매개변수의 이름이 되어진다. 그래서 Account인스턴스를 하나 만들고, Account인스턴스에 credit프로퍼티 값을 1000으로 변경하고, 실행하게 되면 변경되기전에 willSet구무니 실행되서 잔액이 0원에서 1000원으로 변경될 예정이라고 나오고, 변경된 후에는 didSet 구문이 실행되서 0원에서 1000원으로 변경되었다고 출력된다. 

 


 

 

타입프로퍼티

 

타입프로퍼티는 인스턴스 생성없이 객체내에서 프로퍼티에 접근을 가능하게 한다. 즉 프로퍼티 타입자체와 연결하는 것을 말한다.

 

→ 타입프로퍼티는 저장프로퍼티와 연산프로퍼티에서만 사용가능하고, static 키워드를 사용하여 정의한다. 타입프로퍼티로 선언된 프로퍼티에 접근하려면 인스턴스를 생성안해도 타입이름과 타입프로퍼티이름을 점으로 연결해주면 접근이 가능하고, 값도 변경 가능하다. 위코드를 보면 타입프로퍼티로 선언된 storedTypeProperty"hello"라는 문자열로 변경시켜주고, storedTypeProperty가 어떤값으로 변경되었는지 확인을 해보면 storedTypeProperty값이 "hello"라는 값으로 변경된 걸 확인 할 수 있다. 이런식으로 타입프로퍼티를 사용하면 변수에 클래스를 할당하여 인스턴스를 생성하지 않고도 프로퍼티를 사용할 수 있다.