Struct

박인준·2019년 12월 9일
0

Swift

목록 보기
14/21

Comparing Structures and Classes

[ 클래스와 구조체 공통점 ]

  • 값을 저장하기 위한 프로퍼티
  • 기능을 제공하기 위한 메서드
  • 초기 상태를 설정하기 위한 생성자
  • 기본 구현에서 기능을 추가하기 위한 확장(Extension)
  • 특정 값에 접근할 수 있는 첨자(Subscript)
  • 특정한 기능을 수행하기 위한 프로토콜 채택
  • Upper Camel Case 사용

=> 형태만 보면 크게 다른게 없어 보임!


[ 클래스만 제공하는 기능 ]

  • 상속 (Inheritance)
  • 소멸자 (Deinitializer)
  • 참조 카운트 (Reference counting)

-> struct에서 소멸은 되나 deinit 메소드를 제공하지 않음
-> struct에 제공하는 기능은 많으니 복습 중요!

값타입 VS 참조타입

class Dog {
  var name = "토리"
}
struct Cat {
  var name = "릴리"
}

let dog = Dog()
let cat = Cat()

dog.name = "릴리" // 주소값에 저장됨 ; 변수가 아닌 주소값이 고정
cat.name = "토리" // cat() name = "릴리"가 저장되어 있음 -> 오류가 남

생성자 비교

  • class는 init매서드만 가능
  • struct는 생성된 property도 생성가능

// 프로퍼티에 초기화 값이 없을 때

class UserClass2 {
  var name: String
  // 초기화 메서드 없으면 오류
  init(name: String) { self.name = name }
}

struct UserStruct2 {
  var name: String
  var age: Int
  
  // 초기화 메서드 자동 생성
  // 단, 생성자를 별도로 구현했을 경우 자동 생성하지 않음
  
//  init(name: String) {
//    self.name = name
//    self.age = 10
//  }
}

let userC2 = UserClass2(name: "홍길동")
let userS2 = UserStruct2(name: "홍길동", age: 10)

-> struct안에 임의로 init메서드를 생성하면 변경되지 않음!


// 지정(Designated) 생성자, 편의(Convenience) 생성자

class UserClass4 {
  let name: String
  let age: Int
  init(name: String, age: Int) {
    self.name = name
    self.age = age
  }
  convenience init(age: Int) {
    self.init(name: "홍길동", age: age)
  }
}

struct UserStruct4 {
  let name: String
  let age: Int
  init(name: String, age: Int) {
    self.name = name
    self.age = age
  }
  
  // Convenience 키워드 사용 X, 지정과 편의 생성자 별도 구분 없음
//  convenience init(age: Int) {
  init(age: Int) {
    self.init(name: "홍길동", age: age)
  }
}

// 따라서 extension에서도 생성자 추가 가능
extension UserStruct4 {
  init(name: String) {
    self.name = name
    self.age = 10
  }
}

let userS4_1 = UserStruct4(name: "홍길동")
let userS4_2 = UserStruct4(age: 20)

-> struct가 가지는 기능들이 다양하고 class와 비슷하지만 다른 부분들을 명확히 파악하여 사용하여야 함!
-> 예제를 이용하여 확인하면 좋을 듯!


property 변경

struct PointStruct {
    var x = 0
    
    //  func updateX() {  // 오류 발생
    //    self.x = 5
    //  }
    
	  mutating func updateX() { // 값타임 property에 접급하려면 mutating을 사용해야 함
	      self.x = 5
      }
  
  
      var updateProperty: Int {
      get { x }
      set { x = newValue }    // 연산 프로퍼티의 setter는 기본적으로 mutating
	}
}

Protocol 적용


protocol Mutate {
//  func update()
    mutating func update()
}

class Myclass: Mutate {
    var x = 0
    func update() {
        self.x = 5
    }
}
// class는 protocol에 선언된 func이 mutating이어도 받아들일 수 있음

struct PointStruct1: Mutate {
  var x = 0
  
  mutating func update() {
    self.x = 5
  }
//struct는 func안에서 나 자신을 변화시키려면 mutating이 반드시 필요함
  
}

애플 권장사항

  • 구조체를 기본으로 사용
  • 클래스를 사용해야 할 때

    Objective-C와 호환성이 필요할 때
    equality(동등성) 외에 identity(정체성, 동일성)를 제어해야 할 때
    RC(Reference Counting)와 소멸자(deinitialization)가 필요할 때
    값이 중앙에서 관리되고 공유되어야 할 때

profile
iOS 개발자가 되기 위해

0개의 댓글