'Property'에 해당되는 글 2건

  1. 2017.06.26 프로퍼티 - Property (2)
  2. 2012.02.05 Objective C <6>. 클래스와 객체(인스턴스)<2> (57)

프로퍼티

프로퍼티는 클래스, 구조체, 열거형과 연관된 값입니다. 타입과 관련된 값을 저장할 수도, 연산할 수도 있습니다.


소스코드


프로퍼티의 종류

  • 인스턴스 저장 프로퍼티
  • 타입 저장 프로퍼티
  • 인스턴스 연산 프로퍼티
  • 타입 연산 프로퍼티
  • 지연 저장 프로퍼티

이번 파트에서는 지연 저장 프로퍼티를 제외한 저장 프로퍼티와 연산 프로퍼티에 대해 알아봅니다.


정의와 사용

프로퍼티는 구조체, 클래스, 열거형 내부에 구현할 수 있습니다. 다만 열거형 내부에는 연산 프로퍼티만 구현할 수 있습니다. 연산 프로퍼티는 var로만 선언할 수 있습니다.

연산프로퍼티를 읽기전용으로는 구현할 수 있지만, 쓰기 전용으로는 구현할 수 없습니다. 읽기전용으로 구현하려면 get 블럭만 작성해주면 됩니다. 읽기전용은 get블럭을 생략할 수 있습니다. 읽기, 쓰기 모두 가능하게 하려면 get 블럭과 set블럭을 모두 구현해주면 됩니다.  

set 블럭에서 암시적 매개변수 newValue를 사용할 수 있습니다.

struct Student {
    
    // 인스턴스 저장 프로퍼티
    var name: String = ""
    var `class`: String = "Swift"
    var koreanAge: Int = 0
    
    // 인스턴스 연산 프로퍼티
    var westernAge: Int {
        get {
            return koreanAge - 1
        }
        
        set(inputValue) {
            koreanAge = inputValue + 1
        }
    }
    
    // 타입 저장 프로퍼티
    static var typeDescription: String = "학생"
    
    /*
    // 인스턴스 메서드
    func selfIntroduce() {
        print("저는 \(self.class)반 \(name)입니다")
    }
     */
    
    // 읽기전용 인스턴스 연산 프로퍼티
    // 간단히 위의 selfIntroduce() 메서드를 대체할 수 있습니다
    var selfIntroduction: String {
        get {
            return "저는 \(self.class)반 \(name)입니다"
        }
    }
        
    /*
     // 타입 메서드
     static func selfIntroduce() {
     print("학생타입입니다")
     }
     */
    
    // 읽기전용 타입 연산 프로퍼티
    // 읽기전용에서는 get을 생략할 수 있습니다
    static var selfIntroduction: String {
        return "학생타입입니다"
    }
}

// 타입 연산 프로퍼티 사용
print(Student.selfIntroduction)
// 학생타입입니다

// 인스턴스 생성
var yagom: Student = Student()
yagom.koreanAge = 10

// 인스턴스 저장 프로퍼티 사용
yagom.name = "yagom"
print(yagom.name)
// yagom

// 인스턴스 연산 프로퍼티 사용
print(yagom.selfIntroduction)
// 저는 Swift반 yagom입니다

print("제 한국나이는 \(yagom.koreanAge)살이고, 미쿡나이는 \(yagom.westernAge)살입니다.")
// 제 한국나이는 10살이고, 미쿡나이는 9살입니다.


응용

struct Money {
    var currencyRate: Double = 1100
    var dollar: Double = 0
    var won: Double {
        get {
            return dollar * currencyRate
        }
        set {
            dollar = newValue / currencyRate
        }
    }
}

var moneyInMyPocket = Money()

moneyInMyPocket.won = 11000

print(moneyInMyPocket.won)
// 11000

moneyInMyPocket.dollar = 10

print(moneyInMyPocket.won)
// 11000


지역변수 및 전역변수

저장 프로퍼티와 연산 프로퍼티의 기능은 함수, 메서드, 클로저, 타입 등의 외부에 위치한 지역/전역 변수에도 모두 사용 가능합니다.

var a: Int = 100
var b: Int = 200
var sum: Int {
    return a + b
}

print(sum) // 300


프로퍼티 감시자


프로퍼티 감시자를 사용하면 프로퍼티 값이 변경될 때 원하는 동작을 수행할 수 있습니다. 값이 변경되기 직전에 willSet블럭이, 값이 변경된 직후에 didSet블럭이 호출됩니다. 둘 중 필요한 하나만 구현해 주어도 무관합니다. 변경되려는 값이 기존 값과 똑같더라도 프로퍼티 감시자는 항상 동작합니다. 

willSet 블럭에서 암시적 매개변수 newValue를 사용할 수 있고, didSet 블럭에서 암시적 매개변수 oldValue를 사용할 수 있습니다.

프로퍼티 감시자는 연산 프로퍼티에 사용할 수 없습니다.


소스코드



정의 및 사용

struct Money {
    // 프로퍼티 감시자 사용
    var currencyRate: Double = 1100 {
        willSet(newRate) {
            print("환율이 \(currencyRate)에서 \(newRate)으로 변경될 예정입니다")
        }
        
        didSet(oldRate) {
            print("환율이 \(oldRate)에서 \(currencyRate)으로 변경되었습니다")
        }
    }

    // 프로퍼티 감시자 사용
    var dollar: Double = 0 {
        // willSet의 암시적 매개변수 이름 newValue
        willSet {
            print("\(dollar)달러에서 \(newValue)달러로 변경될 예정입니다")
        }
        
        // didSet의 암시적 매개변수 이름 oldValue
        didSet {
            print("\(oldValue)달러에서 \(dollar)달러로 변경되었습니다")
        }
    }

    // 연산 프로퍼티
    var won: Double {
        get {
            return dollar * currencyRate
        }
        set {
            dollar = newValue / currencyRate
        }
        
        /* 프로퍼티 감시자와 연산 프로퍼티 기능을 동시에 사용할 수 없습니다
        willSet {
            
        }
         */
    }    
}

var moneyInMyPocket: Money = Money()

// 환율이 1100.0에서 1150.0으로 변경될 예정입니다
moneyInMyPocket.currencyRate = 1150
// 환율이 1100.0에서 1150.0으로 변경되었습니다

// 0.0달러에서 10.0달러로 변경될 예정입니다
moneyInMyPocket.dollar = 10
// 0.0달러에서 10.0달러로 변경되었습니다

print(moneyInMyPocket.won)
// 11500.0



관련문서

The Swift Programming Language - Properties





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 


'Swift > 기본문법' 카테고리의 다른 글

인스턴스의 생성과 소멸  (0) 2017.07.03
상속  (0) 2017.06.29
프로퍼티 - Property  (2) 2017.06.26
클로저 - Closure  (0) 2017.06.22
클래스, 구조체, 열거형 비교  (0) 2017.06.19
열거형 - Enumerations  (0) 2017.06.15
Posted by yagom

오늘의 주제

1. Class 만들어보기 
2. Class Method, Getter, Setter, Instance Method... 



여섯 번째 시간입니다.^^

지난 번에클래스와 인스턴스에 관한 개요를 알아보았습니다.
하지만, 말로만 듣고는 잘 감이 안오시지요?
물론 이번 포스팅을 보아도 아리송 하실 수 있습니다.
정말 짧은 코드이지만 많은 내용이 담겨져 있으니 이번 포스팅도 보고 또 보셔야 할 듯 합니다^^
정말 중요한 것이니 몇 번을 보고, 다른 싸이트를 검색하고, 직접 계속 둘러보면서 꼭 몸으로 익히도록 하세요~!

자 그럼 오늘은 직접 클래스를 한 번 만들어 보도록 합시다~
출바알~~~~~~~~~~~~


# Class 만들어 보기


자... 새로운 프로젝트를 만들고 아래 그림처럼 새로운 클래스 생성을 위해 New File...을 선택합니다~


자, 그 후에는 Objective-C class라는 녀석을 선택 한 후 Next ~!



자, 클래스 이름은 MyFirstClass로 만들어 주겠습니다. Subclass of 란에는 NSObject를 선택해 주세요~


저장경로는 그대로 놔두고 Create~!


자~ 새로운 클래스가 생성되어있습니다!!


# Class Method, getter, setter, Instance Method...

자동으로 생성된 코드를 한 번 봅시다요~
Foundation헤더가 자동으로 import되어있구요~
@interface MyFirstClass : NSObject

@end

이렇게 생성되었네요~
우리 사용자 인터페이스 뭐 이런말 많이 하잖아요? 인터페이스 뭐 감이 오시죠?
클래스의 요모조모를 만들어 줄 수 있는 영역입니다.
@end는 말그대로 끝!
그러니까 저 빈 공백 사이를 우리가 채우게 되면 클래스의 모양을 완성하는 것이라는 느낌이 오지 않나요? 오홍홍
 : NSObject의 뜻은 NSObject의 Subclass라는 이야기 입니다. NSObject를 상속받은 것이지요... 뭐 더 자세한 것은 다음에 설명해 보도록 할게요..^^
 


자 내용을 채워넣어 봅니다...
빨간 네모박스대로 코드를 넣어봅시다..^^  




자~ 이제 코드 설명 들어갑니다~

중괄호 { } 안에 들어가 있는 세 녀석들이 있습니다.
이녀석들을 instance variable 즉, '인스턴스변수'라고 합니다.
지난 번에 설명드렸던 것 중에 틀 안에 클래스마다 가지고 있는 특징들을 저장하는 빈공간들이 있다고 설명드렸을 거예요~
이녀석들이 그 녀석들입니다.
인스턴스는 클래스의 틀을 가지고 만들어 지는 거잖아요? 지금 우리는 클래스 틀을 만드는 중이구요~
그래서 인스턴스가 새로 똻!!!!! 만들어지면 저 세 녀석들을 가지고 태어납니다. 물론 저 세 녀석들은 텅텅 빈 멍텅구리이지요^^
저기 세 녀석들에 뭐가 들어가냐에 따라서 이 인스턴스는 다른녀석들과 겉모양과 틀은 같아도 내용이 다른 인스턴스(객체)가 되는 것이랍니다.
이녀석은 하나의 integer변수와 두개의 string을 가지고 있네요~

중괄호가 닫히고 @property라는 녀석들이 있네요.
이 property와 다음 그림의 구현파일에서 볼 수 있는 @synthesize라는 녀석과 짝을 이루어서 자동으로 접근자 메소드 들을 생성해 주는 역할을 합니다.
말로만 해서는 잘 이해가 안가시죠?ㅎ 접근자(getter, setter)녀석들을 직접 만들어 쓰는게 정말 귀찮거든요..^^ 그것은 이따가 구현파일 보면서 다시 설명해 드리도록 하지요~
그리고 property옆쪽 괄호 안에 들어가 있는 녀석들은 이 변수들을 꺼내 쓰고 집어넣을때 등등 뭐 이녀석들을 어떻게 관리할지 명시해 주는 옵션 같은 녀석들인데요, 지금은 일단 넘어가도록 합시다^^ 이것만 해도 골치아프잖아요~ㅎㅎ 

그 아래에는 메소드들이 명시되어 있는데요, 일단 메소드에 대해 간략하게 이야기 해보자면,
메소드라는 녀석들은 무엇인가를 수행하는 역할을 합니다.
쉽게 설명을 해서 전자레인지는 우리가 차가운 음식을 집어넣고 버튼을 누르면 데워서 뜨거운 음식으로 만들어 줍니다. 즉, 찬음식을 데워서 뜨거운 음식을 만드는 일련의 과정을 수행하는 역할을 하지요.
메소드도 우리가 메소드에게 일할거리를 던져주면 메소드의 고유한 역할들을 수행합니다.
감이 오시나요?ㅎ
여튼, 여기 헤더파일(.h)에서는 이런 메소드가 있다~ 정도만 말해주고, 그녀석들의 역할을 구현파일(.m)에서 명시해 줍니다.


다시 돌아와서 @property아래에보면 - 로 시작하는 메소드 들이 쭈욱 나열되어 있습니다.
요녀석들을 우리는 '인스턴스 메소드'라고 부릅니다.
요녀석들은 클래스라는 틀에서 찍혀 나온 후에만 동작하는 녀석들입니다.
즉, 인스턴스에서만 작동하는 녀석입니다.

그 아래에 보면 +로 시작하는 '클래스 메소드'가 보입니다.
이녀석도 메소드이긴 하지만 좀 독특한 녀석입니다. 클래스라는 틀이 하나의 인스턴스를 찍어내기도 전에 뭔가의 역할을 할 수 있는 녀석입니다.
잘 이해가 안가시죠? 자동차 공장에서 차를 만드는 생산라인에서 뭔가를 할 수 있다... 즉, 만들어지는 차가 아닌 생산라인 자체에서 뭔가를 수행한다는 의미로 받아들이시면 될 듯 합니다. "차 생산을 시작해라!" 라는 명령 같은 것이 되겠죠?ㅎ
그렇다면 자동차안에 있는 고유의 특성들(인스턴스 변수들)은 이 클래스 메소드 안에서 쓰일 수 없겠군요^^

말이 참 어렵지요? 헷갈리기도 무지하게 헷갈리구요...ㅎㅎ

그럼 이제 구현파일로 가서 이 메소드라는 녀석들이 무엇을 하는 녀석들인지 속삭여 줄 때가 되었네요 ㅎ


자, @synthesize라는 녀석은 @property와 짝을 이뤄서 getter와 setter를 자동으로 만들어 준다고 말씀드렸어요~
@property에서는 변수형, 변수명을 모두 명시해 주지만, @synthesize에서는 변수명만 기재해 줍니다.
@property에서 토스~ @synthesize에서 스파이크~ ㅋㅋㅋ 농담입니다~~~~~~

여튼 아래에 보시면 아까 헤더파일에서 정의해 주었던 메소드들이 하는 역할들이 쭈욱 나열되어 있는 것을 볼 수 있으실 거예요~

캡쳐 화면에서 오타가 있습니다.
인스턴스를 설정해 준다. 인스턴스를 반환한다. (x)
인스턴스 변수를 설정해 준다(setter), 인스턴스 변수를 반환한다(getter). (o)

여튼 메소드들의 역할들은 주석으로 설명을 달아놓았으니 대충 짐작하시리라 믿습니다.
그래도 혹시몰라 다시 간략히 설명하자면

호출한다라는 것은 그 메소드에게 일을 명령한다는 것으로 해석하시면 되겠습니다.
즉 myFirstMethod라는 인스턴스 메소드를 호출하면 NSLog를 남기는 역할을 수행하는 것입니다.

다음에 setMySecret:이라는 인스턴스 메소드를 호출하면 mySecret라는 인스턴스 변수에 secret이라는 녀석을 통해 받아온 값을 저장해 주는 역할을 수행합니다. 이러한 형태를 우리는 setter라고 부릅니다. mySecret이라는 녀석을 setting해주는 녀석이라 이말이죠 ㅎ. 메소드에 대해서는 다음번(바로 다음번)에 자세하게 다룰 것이므로 잘 모르겠어도 '이 메소드는 mySecret이라는 녀석에 뭔가를 집어넣는 녀석이구나' 라고 생각하세용~

다음은 mySecret이라는 녀석의 값을 알아보는 메소드 입니다. 메소드 이름도 getMySecret이네요^^
mySecret의 내용을 불러오는 메소드 입니다. 이런 형태의 녀석을 getter라고 하죠~

자, 이렇듯 mySecret이라는 하나의 녀석을 넣고 빼고 하려면 복잡하고 귀찮게 두개의 메소드를 따로 만들어 줘야 하는데, 그 수고를 덜어주는 녀석들이 바로 @property, @synthesize 되겠습니다^^ 조금 감이 오실까요?ㅎ 요~ 밑에 가시면 좀 더 이해가 가실거예요~

마지막으로 itIsClassMethod라는 클래스 메소드가 구현되어 있습니다.
사실 클래스 메소드는 이런 시시한 역할을 하지는 않지만, 예를 들어보기 위해 제가 만들어 본 것입니다..ㅎㅎ
어쨌거나 저쨌거나~ 위에서 말했든 이녀석은 +로 시작을 하므로 클래스 메소드이고, 인스턴스가 되기도 전에 호출이 가능 합니다~
호출하면 로그를 남기는 역할을 수행하는군요~

이렇게 구현파일 탐험이 끝났습니다~ㅎㅎ

그럼 이렇게 만들어진 클래스를 직접 구워 삶아 보아야 겠지요?ㅎ

main구현파일로 가봅시다~!


네, 또 한바탕 타이핑 합니다 ㅎㅎ
참참참, 스크린샷에 빼놓은 부분이 있는데요, #import "MyFirstClass.h" 해주셔야 합니다~
import뒤에 누구는 <> 해주고 누구는 "" 해주냐구요?ㅎ
<>를 해주는 녀석은 기본 헤더파일, "" 해주는 녀석은 우리가 직접 만들거나 외부에서 가져온 헤더파일 이라고 이해하시면 쉽겠습니다~

여튼 메인 안에 작성해 봅시다요~
(꼭 autoreleasepool 안에 작성하지 않으셔도 됩니당..ㅋㅋ)

뭐 여튼 그럼 이제 코드를 한 번 뜯어봅시다~
일단 코멘트를 보고 한 번 이해해 보려 노력해보세요~

메소드를 호출하는 방법입니다.
[클래스 또는 인스턴스의 이름 (띄어쓰기) 메소드 이름]

이런식이죠
[MyFirstClass itIsClassMethod]
아까 말씀드렸듯이, 우리는 아무런 인스턴스 생성도 하지 않았지만 클래스 메소드를 호출했습니다.

그 아래에는 인스턴스를 선언하고 초기화 합니다.
MyFirstClass *instance ;
'instance라는 이름을 가진 MyFirstClass 클래스의 인스턴스를 만들어라' 라는 의미입니다.
거기에 [[MyFirstClass alloc] init] 이라고 있는데, 이 alloc과 init이 대표적인 클래스 메소드가 되겠습니다...ㅎㅎ
이 의미는 MyFirstClass를 메모리에 할당하고 초기화하여 인스턴스를 생성한다.. 뭐 이런 의미입니다!
깊이들어가면 한도끝도 없어서... 뭐 이런 의미^^

그렇다면 MyFirstClass *instance = [[MyFirstClass alloc] init]; 이라는 녀석은 instance라는 인스턴스에 MyFirstClass라는 클래스를 초기화하여 집어넣어 주어라. 정도의 의미가 되겠습니다~

여튼 이렇게 우여곡절 끝에 인스턴스가 생성되었습니다.

그럼 이제 이 인스턴스(객체)안에 특징(내용물) 즉, 인스턴스 변수들을 세팅해 줘 봅시다.

myName이라는 인스턴스 변수에는 yagom이라고 넣어 주었습니다. 

그리고 NSString클래스의 인스턴스 변수 name이라는 녀석에다가 instance 인스턴스의 myName이라는 인스턴스 변수의 내용을 불러와서 집어넣어 줍니다.

그런데 여기서 잠깐!! 우리는 myName이라는 녀석의 getter와 setter를 만들어주지 않았는데요???
그렇죠!?
바로 @property와 @synthesize 녀석들이 자동으로 만들어 주었기 때문입니다~!

아래에 몇줄도 다 같은 내용들입니다~
주석을 잘 읽어 보시구요..^^
혹여나 이해가 안가는 부분은 댓글 주세요 ㅎㅎ

자, 그럼 대망의 결과를 확인해 볼까요?ㅎㅎㅎ


이런식으로 로그들이 찍히네요~!

정말 자세히 쓰면 한도끝도 없고, 간단히 쓰려니 간단히 쓰는것도 어렵네요..^^
지루하고 힘드셨을텐데 여기까지 읽어주셔서 감사합니다!!
여기까지 읽으신 분이 계실지도 의문이네요^^
혹여나 읽으셨다면 힘내라고 댓글 하나만 ...!! 넙죽넙죽...

정말 오래걸렸네요^^
다음에 또 알찬 내용으로 다시 올게요~
부족한 부분은 댓글 꼭 주시구요~!

뿅~!

by yagom

p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓저 열심히 썼는데 추천 한방 꾹 눌러주고 가시는 건 어떨까요? ^~^ 사랑합니다~ ↓↓↓
Posted by yagom