티스토리 뷰

Swift

Swift ) Properties - Type Properties

Zedd0202 2017. 10. 13. 14:35
반응형


자 < Stored Property(저장 프로퍼티)>에서 말했던 Swift에는 3가지 종류의 프로퍼티가 있다고 한 것 기억나시나요?

우리는 <Stored Property(저장 프로퍼티)>에서 저장프로퍼티를 봤고,

<Computed Property(연산프로퍼티)>에서 연산프로퍼티를 봤습니다!

그리고...이제 이 글에서 나머지 프로퍼티인 Type Property(타입 프로퍼티)를 볼거에요 :)





Type Properties




타입 프로퍼티에 말하기 전에, 앞으로 제가 계속 인스턴스 프로퍼티(instance property)라고 계속 언급할 건데, 이 "인스턴스 프로퍼티"란, 특정 타입의 인스턴스에 속하는 프로퍼티에요. 이때까지 말한, 특정한 구조체, 클래스에 속하는 저장프로퍼티와 연산프로퍼티가 바로 인스턴스 프로퍼티에요.

(연산프로퍼티는 ENUM에도 추가 가능했었죠?)


우리 < Stored Property(저장 프로퍼티)>글 첫부분에서 잠깐 타입프로퍼티에 대해 설명했었죠.

프로퍼티를 타입 자체와 연결할 수도 있어요. 이러한 프로퍼티를 Type Property(타입 프로퍼티)라고 합니다. 

조금만 더 알아봅시다.

타입 프로퍼티는 모든 타입이 사용할 수 있는 상수 프로퍼티(constants property) (ex : C의 static 상수)

또는 글로번 변수 프로퍼티와 같이 특정 타입의 모든 인스턴스에 공통적인 값을 정의하는 데 유용합니다. ( ex: C의 static 변수)


저장 타입 프로퍼티(Stored type Property)는 변수 또는 상수일 수 있습니다.

연산 타입 프로퍼티(Computed type Property)는 Computed instance property와 같이 항상 변수 프로퍼티로 선언됩니다. 


하지만, 저장 인스턴스 프로퍼티(Stored instance property)와 달리 저장 타입 프로퍼티(Stored type Property)에는 항상 기본값(default value)을 줘야합니다. 왜냐하면 초기화 시에, 타입 자체에는 저장 타입 프로퍼티(Stored type Property)에 값을 할당할 initializer가 없기 때문입니다. 


저장 타입 프로퍼티는 처음 엑세스 할때는 게으르게 초기화(lazily initialized)합니다.

이것은 다수의 thread에 의해 동시에 엑세스 되고 있어도, 한번만 초기화되는 것이 보증되어 있어 "lazy" 라는 키워드를 사용할 필요는 없습니다.



으아 복잡하네요.. 저장 인스턴스 프로퍼티랬다가..저장 타입 프로퍼티랬다가..위 설명은 저장 인스턴스 프로퍼티와 저장 타입 프로퍼티가 익숙해지시면 천천히 읽어보시는 것을 추천드려요.

위 설명을 정리하자면!!!


1. 프로퍼티를 "타입 자체"에 연결할 수 있는데, 그게 타입 프로퍼티야

2. 타입프로퍼티에는,  저장 타입 프로퍼티와 연산 타입 프로퍼티가 있어!

3. 저장 타입 프로퍼티는 상수/변수 일 수 있어!! -> let / var로 선언이 가능, 또한 무조건 기본값을 줘야해,  또!! 처음 엑세스 할 때는 초기화를 게으르게해!! 하지만 lazy키워드는 필요없어 ㅎㅎ

4. 연산 타입 프로퍼티는 무조건 변수로 선언되어야해 -> var로만 선언이 가능


이렇게 됩니다. 

조금 헷갈리죠?


설명을 더 볼게요.

C 및 Objective-C에서, 타입과 연결된 static 상수와 static 변수를 정의할 수 있었어요.

그러나, Swift에서 타입 프로퍼티는 타입 정의의 "일부로" 타입의 외부 중괄호 안에 쓰여지며, 각 타입 프로퍼티는 명시적으로 지원하는 타입으로 범위가 지정되게 됩니다. 


"static"키워드를 사용하여 타입 프로퍼티를 정의할 수 있습니다.

클래스 타입에 대한 연산 타입 프로퍼티(Computed type property)의 경우, "class" 키워드를 사용하여 서브클래스가 슈퍼클래스의 구현을 재정의(override)할 수 있습니다. 아래예제는 연산 타입 프로퍼티(Computed type property)의 문법입니다. 


아~~~~~정말 이해가 안가죠..제 번역실력...이란....하지만, 아래 예제를 보시면 조금 이해가 가실겁니다. 


struct SomeStructure {

    static var storedTypeProperty = "Some value."

    static var computedTypeProperty: Int {

        return 1

    }

}

자, 차근차근 하나씩 살펴보자구요. SomeStructure라는 "구조체"를 하나 선언했네요.

그 안에는? static 키워드를 사용한 어떤 것들이 있어요!!!

static이 사용되지 않았으면..아 그냥 저장 인스턴스 프로퍼티, 연산 인스턴스 프로퍼티구나...(이전 글에서는 그냥 저장프로퍼티, 연산 프로퍼티 라고 그랬었죠?)

라고 생각했을텐데!!! 앞에 static이라는 키워드가 붙었으니..우리는

아!! 얘네는 타입 프로퍼티구나! 라는 것을 알 수 있습니다. 


storedTypeProperty는 딱 봐도 저장 타입 프로퍼티같죠? 저장 인스턴스 프로퍼티와는 다르게 "기본값"을 준걸 볼 수 있어요. 저장 인스턴스 프로퍼티에서는 기본값을 안줘도 됐었는데 말이에요. 


struct FixedLengthRange {

    var firstValue: Int

    let length: Int

}


var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)


rangeOfThreeItems.firstValue = 6

rangeOfThreeItems.length = 10//error!

이렇게요! <저장 프로퍼티> 글에서 봤었죠?

computedTypeProperty는 딱 봐도 연산 타입 프로퍼티네요. 위에서 말한 연산 타입 프로퍼티의 특징이 뭐였죠? 


네.. 무조건! var로 선언이 되어야 한다는 점 ㅎㅎ기억해주세요.

보니까, get만 선언되어있는 것 같네요 :)



자, 다음 예제~~~ 

enum SomeEnumeration {

    static var storedTypeProperty = "Some value."

    static var computedTypeProperty: Int {

        return 6

    }

}

엇 enum이 나왔네요 :) 열거형이죠?

근데 여기서 유심히 봐야할 부분이 있습니다.

우리 < Stored Property(저장 프로퍼티)> 글에서 

저장 (인스턴스) 프로퍼티는 분명히..클래스와 구조체에서만 사용된다고 했는데

저장 타입 프로퍼티는 enum(열거형)에서 사용될 수 있나봅니다!!

역시나 static키워드와 함께 기본값을 준 것. 보이시죠?

연산 타입 프로퍼티도 위 구조체와 마찬가지로 get만을 구현해줬네요.


다음예제~~~


자, 이번 예제는 조금 유심히 봐야해요 :)

예제를 보기 전에, 아까 제가 말한

"클래스 타입에 대한 연산 타입 프로퍼티(Computed type property)의 경우, "class" 키워드를 사용하여 서브클래스가 슈퍼클래스의 구현을 재정의(override)할 수 있습니다."

라는 말을 다시한번 기억해주세요 :)


class SomeClass {

    static var storedTypeProperty = "Some value."

    static var computedTypeProperty: Int {

        return 27

    }

    class var overrideableComputedTypeProperty: Int {

        return 107

    }

}

자...평범하게 저장 타입 프로퍼티와 연산 타입 프로퍼티가 나온 것을 볼 수 있습니다.

하지만 밑에 하나가 더 있네요?

"static"이라는 키워드가 붙지 않고, "class"라는 키워드가 붙었어요! 

"클래스 타입에 대한 연산 타입 프로퍼티(Computed type property)의 경우,  "class" 키워드를 사용하여 서브클래스가 슈퍼클래스의 구현을 재정의(override)할 수 있습니다." 라고 그랬으니까, overrideableComputedTypeProperty는 class키워드가 붙었으니 일단은 연산 타입 프로퍼티겠네요. :)

구현을 재정의 할 수 있다는 말을 조금 풀어서 쓰면,

저 SomeClass를 상속받은 어떤 클래스는, "class"라는 키워드가 붙은 저 overrideableComputedTypeProperty라는 연산 타입 프로퍼티를 재정의 할 수 있다는 말이에요.

역시나 말로하면...굉장히..어렵..습니다..한번 예제를 같이 볼까요? 


class ChildSomeClass : SomeClass{

    override static var overrideableComputedTypeProperty: Int{

        return 2222

    }

}

이것이!!!된다는 소리죠. 

ChildSomeClass는 우리가 위에서 본 SomeClass를 상속받은 서브클래스죠?

SomeClass가 슈퍼클래스이구요. SomeClass에 있던 "class"라는 키워드가 붙은 overrideableComputedTypeProperty라는 연산 타입 프로퍼티는 이렇게 서브클래스인 ChildSomeClass에서 "재정의"가 가능하답니다. 당연히 앞에는 override키워드가 붙어야겠죠?

그러면, class가 "안붙은" 평범한 연산 타입 프로퍼티를 재정의하면 어떻게될까요?


class ChildSomeClass : SomeClass{


    override static var computedTypeProperty:Int{

        return 123//error! cannot override static var

    }

}


이렇게 재정의 할 수 없다며 에러를 내고 맙니다. :)

조금 이해가 가시나요!?!??


다음으로 넘어갈게요. 


Querying and Setting Type Properties(타입 프로퍼티 조회와 설정?)




우리가 인스턴스 프로퍼티에서 했던것 처럼, 타입 프로퍼티 역시 조회와 값 세팅은 .(점)을 통해 이루어지는데요.

인스턴스 프로퍼티와는 조금 다른점이 있습니다. 

위에서 우리 구조체, 열거형, 클래스를 하나씩 정의했었죠?

그것들을 이용하는데, 그전에!

원래같으면 


struct FixedLengthRange {

    var firstValue: Int

    let length: Int

}


var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)


rangeOfThreeItems.firstValue = 6

rangeOfThreeItems.length = 10//error!

이렇게 해당 구조체, 열거형, 클래스의 인스턴스를 하나 만들고!!!!!그 인스턴스를 통해서 프로퍼티들에 접근을 했었어요.

하지만, 타입프로퍼티는


print(SomeStructure.storedTypeProperty)

// Prints "Some value."

SomeStructure.storedTypeProperty = "Another value."

print(SomeStructure.storedTypeProperty)

// Prints "Another value."

print(SomeEnumeration.computedTypeProperty)

// Prints "6"

print(SomeClass.computedTypeProperty)

// Prints "27"


이렇게 타입 "자체"의 이름을 치고,  .(점)을 통해 프로퍼티에 접근하네요!!!!

SomeStructure, SomeEnumeration, SomeClass

은 구조체, 열거형, 클래스의 이름이었죠? :)

타입자체의 이름을 통해 프로퍼티에 접근하는 것만 빼고, 인스턴스 프로퍼티와 사용하는 법은 같아요 XD



인스턴스 프로퍼티와 타입 프로퍼티의 차이점을 조금 아시겠나요?

이제 


프로퍼티를 타입 "자체"와 연결할 수 있다는 말이 감이 좀 오시나요? XD

저는 프로퍼티를 타입자체와 연결한다는게 이해가 안가서..

원래 이런뜻이 아닌데 제가 번역을 잘못하고 있는건지 했는데, 이제 잘 이해가 갑니다 :)


드디어 Swift의 프로퍼티 시리즈?..가 끝났는데, 궁금하신 점이나, 지적할 점은 댓글이나 PC화면 오른쪽 하단에 있는 채널서비스를 이용해 메세지 주세요 :)

안녕~~



반응형