Class & Struct

공식 문서: Structures and Classes


1. 사용자 정의 타입

개발자가 직접 타입을 구현하고 싶을 때 사용자 정의타입인 class, struct, enum을 사용한다.
Basic type인 Int, String, Bool도 내부적으로 struct를 사용한다는 것을 알 수 있다

@frozen public struct Int : FixedWidthInteger, SignedInteger { ... }

2. Class의 초기화 방식

class의 initializing type(초기화 방식)은 초기값 지정과 생성자 생성으로 구분할 수 있다.
둘다 하지 않으면 “Class ‘SwiftClass’ has no initializers” 오류가 뜬다

class SwiftClass {
    var apple = "사과"
    var bear: String
    var count: Int
}
class SwiftClass {
    var apple = "사과"
    var bear: String
    var count: Int

    init(bear: String, count: Int) {
        self.bear = bear
        self.count = count
    }
}

let data = SwiftClass(bear: String, count: Int)

3. Struct의 Initializer

Struct는 생성자를 자동으로 만들어주는 기능이 있다. 이를 Memberwise 기능이라고 한다.
아래와 같이 초기값이 있는 apple은 선택, bear와 count은 필수로 값을 담는다.

struct SwiftStruct {
    var apple = "사과"
    var bear: String
    var count: Int
}

let data = SwiftStruct(bear: String, count: Int)
struct SwiftStruct {
    var apple = "사과"
    var bear: String
    var count: Int?

    init(apple: String, bear: String) {
        self.apple = apple
        self.bear = bear
    }
}

let data = SwiftStruct(apple: String, bear: String)

4. 상속관계

Class는 상속이 가능하지만 단일 상속만 가능하며, Struct는 상속이 불가능하다.
아래의 코드에서 Zero는 One의 부모 객체이다. 반대로 One은 Zero의 자식 객체이다
One을 상속받은 Two도 Zero의 함수를 사용할 수 있는데, 상속의 특징은 수직과 중첩이다.

class Zero {
    func zeroFunc() { }
}

class One: Zero {
    override func zeroFunc() {
        super.zeroFunc()
    }

    func oneFunc() { }
}

  

class Two: One {
    override func zeroFunc() {
        super.zeroFunc()
    }

    override func oneFunc() {
        super.oneFunc()
    }
}

5. Instance

struct SwiftStruct {
    var apple = "사과"
    var bear: String
    var count: Int?
}

let word = SwiftStruct(bear: "곰", count: 2)

SwiftStruct 생성자의 값은 Instance이다.
즉, word의 타입은 SwiftStruct이고 값은 SwiftStruct의 Instance이다!
생성자를 통해 let word, let word2 와 같은 개별적인 값을 가진 인스턴스를 생성할 수 있다.

6. Static(전역)

struct SwiftStruct {
    static var apple: String?
    var bear: String
}

let word = SwiftStruct(bear: String)

bear은 SwiftStruct의 생성자에 포함되어 있다. → bear은 인스턴스 프로퍼티이다
apple은 생성자에 포함되어 있지 않다 → 앞에 static 붙으면 타입 프로퍼티가 된다

struct SwiftStruct {
    static var apple: String?
    var bear: String
}

SwiftStruct.apple

Swiftstruct 타입을 참조하면 apple 프로퍼티가 뜬다

7. 참조 타입과 값 타입

Class (reference type) = 참조 타입 (주소 값을 참조한다)
Struct (value type) = 값 타입(값을 저장한다)

class SwiftClass {
    var name: String
    
    init(name: String) {
        self.name = name
    }
}

let valueC = SwiftClass(name: "이름")
valueC.name = "Class 이름"

struct SwiftStruct {
    var name: String
}

let valueS = SwiftStruct(name: "이름")
valueS.name = "Struct 이름" //Cannot assign to property: 'valueS' is a 'let' constant, Change 'let' to 'var' to make it mutable
class SwiftClass {
    var name: String

    init(name: String) {
        self.name = name
    }
}

let valueC = SwiftClass(name: "이름")
let valueC2 = valueC
valueC2.name = "222 이름"
print(valueC.name)
print(valueC2.name)

print("--------------------")

struct SwiftStruct {

    var name: String
}

let valueS = SwiftStruct(name: "이름")
var valueS2 = valueS
valueS2.name = "222 이름"
print(valueS.name)
print(valueS2.name)


결과:
222 이름
222 이름
--------------------
이름
222 이름

위 코드에서 valueS는 let이라서 name 값을 바꿀 수 없었다. 만약 valueS2를 수정 시 valueS의 값이 변경된다면 valueS은 let으로 선언되어 있기 때문에 오류가 났을 것이다