# 구조체와 클래스 1.

### Struct는 값 타입이다. (Value Type)

- 구조체는 클래스와 다르게 메모리의 스택 영역을 활용하는 값 타입의 틀이다.

- 구조체로 만든 인스턴스는 '값' 그 자체로 인식되고 저장되어 사용된다. (스택의 한 영역을 차지하고 사용된다.)

    - 그래서, 어떤 구조체로 만든 인스턴스를 다른 변수에 할당하더라도 **서로 다른 '값'**으로 인지된다.

```
struct A {
    var property: String
}

var a = A(property: "a")
var b = a
b.property = "b" 
print(a.property, b.property) // "a" "b"
```

### Class는 참조 타입이다. (Reference Type)

- 클래스는 구조체와 다르게 메모리의 힙 영역 주소값을 활용하는 **참조 타입의 틀**이다.

- 클래스로 만든 인스턴스는 '주소'에 대한 정보를 바라보고 있기 때문에, **해당 주소 내부의 값이 변경되면 자신의 값도 자연스럽게 변경**한다.

    - 그래서, 어떤 클래스로 만든 인스턴스를 다른 변수에 할당하면 참조하고 있는 주소의 값 변화에 따라 동일하게 변화한다. (저장 장치를 함께 사용하는 느낌이다.)

    - 구조체와 동일하게 인스턴스를 생성하여 멤버를 초기화하면 스택 영역에 저장 장소를 각각 가지고, 힙의 클래스 주소 정보를 가지게 된다.

### 멤버

- 인스턴스 저장 멤버 (저장 property)

    - 다른 언어들과 마찬가지로 값을 저장할 수 있는 멤버를 지정할 수 있고, 생성자(init) / 초기 값 할당의 방식으로 초기화 할 수 있다.

    - 이 말은 Optional한 타입으로 초기 값으로 할당할 수 있다는 말인데(ex.  `var a: String?` ), 이 멤버의 값을 초기화 하지 않으면 nil로 초기화 되기 때문에 런타임 에러가 발생할 수 있다.

    - 지연 저장 멤버(lazy var)를 지정할 수도 있는데, 이 멤버는 **자신이 호출되는 시점에 초기화**가 된다.

```
struct Media {
    let name: String
    let series: Int
    lazy var rate: Double = 4.0 // 구조체, 클래스 선언 당시에 초기값이 필요하다.
}

let squidgame = Media(name: "오징어게임", series: 8) // rate는 초기화 되지 않음
squidgame.rate // 여기서 초기화 됨
```

- 타입 저장 멤버 (저장 property)

    - 인스턴스와 무관하게 클래스, 구조체 타입 자체에서 값을 저장하고 사용할 수 있는 멤버다.

    - 다른 언어와 비슷하게 static 키워드로 구분되고, lazy를 붙인 멤버와 비슷하게 호출 시점에 초기화 된다.

- 연산 멤버

    - getter, setter를 이용해 구조체, 클래스, 심지어 열거형과 extension 키워드로 관리되는 클래스 내부에서 연산형 멤버를 작성할 수 있다.

    - getter, setter를 잘 활용하면, private 제어자로 숨겨진 저장 멤버의 값에 직접 접근하지 않고 안전하게 외부로 가져오거나 새로운 값으로 덮어씌울 수 있다. (newValue)

```
struct User {
    private var name: String
    private var age: Int
    static private var key = "user"

    var getOrChangeName: String {
        get {
            return self.name
        }

        set {
            self.name = newValue
        }
    }

    // 물론 타입 멤버도 이렇게 연산형으로 활용가능하다.
    static var getOrSaveUser {
        get {
            return UserDefaults.standard.string(forKey: User.key)
        }

        set {
            UserDefaults.standard.setValue(newValue, forKey: User.key)
        }
    }
}
```

For the site tree, see the [root Markdown](https://slashpage.com/hankyeol.md).
