본문 바로가기

iOS/Swift

Swift 공식문서 9. Structures and Classes

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures

Documentation

docs.swift.org


Comparing Structures and Classes

공통점

  • 저장 프로퍼티 정의 가능
  • 메서드 정의 가능
  • subscripts 정의 가능
  • 생성자로 초기 값 설정 정의
  • Extension으로 기본 구현에 기능을 확장 가능
  • Protocol 채택 가능

클래스가 추가적으로 갖는 것

  • 하나의 클래스 상속 가능
  • 타입 캐스팅으로 런타임에 클래스 인스턴스의 타입을 확인하고 해석 가능
  • Deinitializer로 클래스의 인스턴스가 할당한 자원 해제 가능
  • (Reference Counting) 클래스 인스턴스에 대해 하나 이상의 참조를 허용

클래스가 더 많은 기능을 제공하는 것에 대한 트레이드-오프가 존재한다.
문서에서는 구조체를 우선 사용하되, 클래스가 적절하거나 필요할 때만 사용하라고 권장하고 있다.
 
https://developer.apple.com/documentation/swift/choosing-between-structures-and-classes

Choosing Between Structures and Classes | Apple Developer Documentation

Decide how to store data and model behavior.

developer.apple.com

 

Choose Structures by Default

 
기본적으로 구조체를 선택하라. 구조체 사용은 상태 변경에 대해 안전하다.

  • 구조체값 타입, 클래스는 참조 타입이다.
  • 따라서 특정 블록 내에서 구조체의 상태가 변경되더라도 다른 부분에 영향을 미치지 않는다.
  • 코드의 특정 부분에서 이뤄지는 변경 사항을 더 쉽게 추적하고 예측할 수 있다.

User Classes When You Need Objective-C Interoperability

Objective-C API가 데이터를 처리해야 하거나,
데이터 모델을 Objective-C 프레임워크에서 정의된 기존 클래스 계층에 맞춰야 한다면
데이터 모델링을 위해 클래스와 클래스 상속을 사용할 필요가 있을 수 있다.
 
ex. Objective-C 기반 프레임워크 UIKit

import UIKit

// UIViewController 서브클래싱
class MyViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // 화면 로드 시 수행할 작업
        view.backgroundColor = .white
    }
}

 

Use Classes When You need to Control Identity

인스턴스가 Identity를 가질 필요가 있을 때 클래스를 사용하라
 
인스턴스가 가지는 Identity 덕분에 여러 곳에서 공유될 때 그 상태가 통일된 방식으로 유지된다.
이 특성 덕분에 파일 핸들, 네트워크 연결, 하드웨어 중개자 같은 공유 리소스를 관리할 때 적합
 
Identity

  • 클래스에는 참조 타입이기 때문에 Identity의 개념이 존재한다.
  • 두 개의 인스턴스가 모두 같은 저장 프로퍼티를 갖더라도, Identity Operator(===)로는 여전히 다른 인스턴스로 간주될 수 있음

 
공유된 참조

  • 클래스 인스턴스는 여러 곳에서 같은 객체를 참조할 수 있다.
  • 클래스 인스턴스가 앱의 여러 부분에서 공유되면, 인스턴스의 변경 사항이 참조하는 모든 곳에 영향을 준다.
  • ex. 파일 핸들
    • 여러 객체에서 동일한 파일에 접근할 수 있어야 하므로, 클래스를 사용하여 이러한 핸들을 공유하는 것이 적절하다.
  • ex. 네트워크 연결
    • 네트워크 연결은 동일한 인스턴스를 공유하면서, 연결 상태나 데이터 처리 로직이 통일되어야 한다.
  • ex. 하드웨어 중개자
    • CBCentralManager 같은 하드웨어 관리 객체는 여러 뷰 컨트롤러나 서비스에서 공유하면서, 동일한 상태를 유지하고 통일된 동작을 해야 한다.
  • 이러한 공유 상태를 관리할 때는 접근 범위를 제한하여 코드 복잡성을 줄이는 것이 중요

 

Use Structures When You Don't Control Identity

Identity를 제어할 수 없는 엔티티는 구조체를 사용하라
 
Swift에서는 구조체가 값 타입이기 때문에, Identity를 제어하지 않거나 그 Identity가 외부 시스템에 의해 관리되는 데이터 모델을 표현할 때 유용하다.
 

struct PenPalRecord {
    let myID: Int        // 식별자, 변경 불가능한 상수
    var myNickname: String
    var recommendedPenPalID: Int
}

var myRecord = try JSONDecoder().decode(PenPalRecord.self, from: jsonResponse)

 

  • myID는 상수로 선언되어 있고, 이 값은 데이터베이스에서 Identity를 나타낸다.
    • 로컬에서 이 값을 변경할 수 없으므로, 잘못된 변경을 방지할 수 있다.
  • myNickname, recommendedPenPalID는 로컬에서 변경 가능하지만, 데이터베이스 수정 이전 로컬에서만 영향을 준다.

 

Use Structures and Protocols to Model Inheritance and Share Behavior

상속이 필요하다고 꼭 클래스를 사용해야 하는 것은 아니다.
상속 계층이 필요할 때 먼저  프로토콜 상속과 구조체를 사용하여 모델링하라
 

  • 클래스 상속 보다 프로토콜 상속을 권장
  • 프로토콜 상속은 더 유연하고, 구조체, 열거형, 클래스 모두에서 사용 가능
 클래스 상속프로토콜 상속
타입참조 타입클래스, 구조체, 열거형 모두 지원
다중 상속불가다중 상속 가능
유연성제한적매우 유연
사용 가능 상황클래스 간의 계층이 필요할 때기능 중심의 상속 및 다양한 타입에서 구현할 때

 

Structures And Enumerations Are Value Types

값 타입(Value Type) 

  • 변수, 상수에 할당되거나 함수로 전달될 때 복사본이 생성된다.
  • Swift의 정수, 부동소수점, 불린, 문자열, 배열, 딕셔너리 등의 타입은 값 타입 (내부적으로 구조체로 구현됨)

Copy-On-Write

  • Collection에서는 최적화된 복사 방식을 사용한다.
  • 즉시 복사되지 않고, 메모리를 공유하다가, 컬렉션 중 하나가 수정될 때 그제야 복사가 이루어지는 방식

ex.

let hd = Resolution(width: 1920, height: 1080)

var cinema = hd
cinema.width = 2048

 

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures/

 

Classes Are Reference Types

참조 타입(Reference Type)

  • 값 타입과 달리 변수, 상수에 할당되거나 함수로 전달될 때 복사되지 않는다.
  • 복사 대신, 동일한 기존 인스턴스에 대한 참조를 사용
    • 여러 참조를 공유하기 때문에 값 타입보다 더 복잡하다.
    • 사이드 이펙 발생 가능성

ex.

let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0

 

https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures/

 

Pointers

  • C, C++, Objective-C와 같은 다른 언어들은 메모리 주소를 참조하기 위해 포인터를 사용한다.
  • Swift의 상수나 변수가 어떤 참조 타입의 인스턴스를 참조할 때,  이는 C의 포인터와 비슷하지만 메모리 주소에 대한 직접적인 포인터는 아니다.
  • Swift 표준 라이브러리는 포인터와 버터 타입을 제공하며, 포인터와 직접 사용할 필요가 있을 때 사용할 수 있다.

'iOS > Swift' 카테고리의 다른 글

Swift 공식문서 8. Enumeration  (0) 2024.10.03
Swift 공식문서 7. Closures  (3) 2024.09.26
Swift 공식문서 6. Functions  (0) 2024.09.20
Swift - In-Out 파라미터  (0) 2024.09.20
Swift 공식문서 5. Control Flow  (0) 2024.09.19