구조체와 클래스 1.

Created by
  • 한결

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) } } }