Programming

왜 수업보다 구조를 선택해야합니까?

procodes 2020. 2. 15. 23:37
반응형

왜 수업보다 구조를 선택해야합니까?


Java 배경에서 나온 Swift로 놀면서 왜 클래스 대신 Struct를 선택하고 싶습니까? 더 적은 기능을 제공하는 Struct와 동일한 기능인 것 같습니다. 왜 그것을 선택해야합니까?


Swift에서 널리 사용되는 WWDC 2015 토크 프로토콜 지향 프로그래밍 ( video , transcript )에 따르면 Swift는 여러 상황에서 클래스보다 구조를 개선하는 여러 기능을 제공합니다.

클래스에서와 같이 동일한 인스턴스에 대한 여러 참조를 갖는 것보다 복사가 훨씬 안전하기 때문에 Structs가 비교적 작고 복사 가능한 경우 선호됩니다. 변수를 여러 클래스 및 / 또는 멀티 스레드 환경으로 전달할 때 특히 중요합니다. 변수 사본을 항상 다른 장소로 보낼 수 있다면 다른 장소가 변수 값을 변경하는 것에 대해 걱정할 필요가 없습니다.

Structs를 사용하면 변수의 단일 인스턴스에 액세스 / 수정하기 위해 메모리 누수 또는 여러 스레드 경주에 대해 걱정할 필요가 없습니다. (기술적으로 생각하면 클로저 내부의 구조체를 캡처 할 때 예외적으로 명시 적으로 복사하도록 표시하지 않는 한 인스턴스에 대한 참조를 캡처하기 때문에 예외입니다.)

클래스는 단일 수퍼 클래스에서만 상속 할 수 있기 때문에 클래스가 부풀어 질 수 있습니다. 그것은 우리가 느슨하게 관련된 많은 다른 능력들을 포함하는 거대한 수퍼 클래스를 만들도록 권장합니다. 특히 프로토콜에 구현을 제공 할 수있는 프로토콜 확장과 함께 프로토콜을 사용하면 이러한 종류의 동작을 달성하기 위해 클래스가 필요하지 않습니다.

이 강의에서는 수업이 선호되는 다음 시나리오를 설명합니다.

  • 인스턴스 복사 또는 비교가 의미가 없습니다 (예 : Window)
  • 인스턴스 수명은 외부 효과 (예 : TemporaryFile)와 연결되어 있습니다.
  • 인스턴스는 "싱크"일뿐입니다. 쓰기 전용 도관을 외부 상태 (예 : CGContext)로

구조체가 기본값이어야하고 클래스는 폴백이어야 함을 의미합니다.

반면에 Swift Programming Language 문서는 다소 모순됩니다.

구조 인스턴스는 항상 값으로 전달되고 클래스 인스턴스는 항상 참조로 전달됩니다. 이것은 다른 종류의 작업에 적합하다는 것을 의미합니다. 프로젝트에 필요한 데이터 구조 및 기능을 고려할 때 각 데이터 구조를 클래스 또는 구조로 정의해야하는지 결정하십시오.

일반적인 지침으로 다음 조건 중 하나 이상이 적용될 때 구조를 만드는 것이 좋습니다.

  • 이 구조의 주요 목적은 비교적 간단한 몇 가지 데이터 값을 캡슐화하는 것입니다.
  • 해당 구조의 인스턴스를 할당하거나 전달할 때 캡슐화 된 값이 참조되지 않고 복사 될 것으로 예상하는 것이 합리적입니다.
  • 구조에 의해 저장된 모든 속성은 자체적으로 값 형식이며 참조가 아닌 복사 될 것으로 예상됩니다.
  • 구조는 기존의 다른 유형에서 속성이나 동작을 상속 할 필요가 없습니다.

구조에 적합한 후보의 예는 다음과 같습니다.

  • 기하학적 유형의 크기로, Double 유형의 너비 속성과 높이 속성을 캡슐화 할 수 있습니다.
  • Int 유형의 시작 속성과 길이 속성을 캡슐화하여 계열 내의 범위를 참조하는 방법입니다.
  • 3D 좌표 시스템의 점으로, 각각 Double 유형의 x, y 및 z 속성을 캡슐화 할 수 있습니다.

다른 모든 경우에는 클래스를 정의하고 참조로 관리 및 전달할 해당 클래스의 인스턴스를 작성하십시오. 실제로 이것은 대부분의 사용자 정의 데이터 구조가 구조가 아닌 클래스 여야 함을 의미합니다.

여기서는 기본적으로 클래스를 사용하고 특정 상황에서만 구조를 사용해야한다고 주장합니다. 궁극적으로, 가치 유형과 참조 유형의 실제 의미를 이해해야하며, 언제 구조체 또는 클래스를 사용할 지에 대한 정보에 근거한 결정을 내릴 수 있습니다. 또한 이러한 개념은 항상 발전하고 있으며 Swift Programming Language 문서는 Protocol Oriented Programming 강연을하기 전에 작성되었습니다.


구조체 인스턴스는 스택에 할당되고 클래스 인스턴스는 힙에 할당되므로 구조체가 때로는 더 빠를 수 있습니다.

그러나 항상 직접 측정하고 고유 한 사용 사례에 따라 결정해야합니다.

and를 Int사용하여 데이터 유형 을 래핑하는 두 가지 전략을 보여주는 다음 예를 고려하십시오 . 나는 여러 개의 필드가있는 실제 세계를 더 잘 반영하기 위해 10 개의 반복 값을 사용하고 있습니다.structclass

class Int10Class {
    let value1, value2, value3, value4, value5, value6, value7, value8, value9, value10: Int
    init(_ val: Int) {
        self.value1 = val
        self.value2 = val
        self.value3 = val
        self.value4 = val
        self.value5 = val
        self.value6 = val
        self.value7 = val
        self.value8 = val
        self.value9 = val
        self.value10 = val
    }
}

struct Int10Struct {
    let value1, value2, value3, value4, value5, value6, value7, value8, value9, value10: Int
    init(_ val: Int) {
        self.value1 = val
        self.value2 = val
        self.value3 = val
        self.value4 = val
        self.value5 = val
        self.value6 = val
        self.value7 = val
        self.value8 = val
        self.value9 = val
        self.value10 = val
    }
}

func + (x: Int10Class, y: Int10Class) -> Int10Class {
    return IntClass(x.value + y.value)
}

func + (x: Int10Struct, y: Int10Struct) -> Int10Struct {
    return IntStruct(x.value + y.value)
}

성능은 다음을 사용하여 측정됩니다.

// Measure Int10Class
measure("class (10 fields)") {
    var x = Int10Class(0)
    for _ in 1...10000000 {
        x = x + Int10Class(1)
    }
}

// Measure Int10Struct
measure("struct (10 fields)") {
    var y = Int10Struct(0)
    for _ in 1...10000000 {
        y = y + Int10Struct(1)
    }
}

func measure(name: String, @noescape block: () -> ()) {
    let t0 = CACurrentMediaTime()

    block()

    let dt = CACurrentMediaTime() - t0
    print("\(name) -> \(dt)")
}

코드는 https://github.com/knguyen2708/StructVsClassPerformance 에서 찾을 수 있습니다.

업데이트 (2018 년 3 월 27 일) :

Swift 4.0, Xcode 9.2에서 iPhone 6S, iOS 11.2.6에서 릴리스 빌드를 실행하면 Swift Compiler 설정은 -O -whole-module-optimization다음과 같습니다.

  • class 버전은 2.06 초 걸렸다
  • struct 버전은 4.17e-08 초가 걸렸습니다 (50,000,000 배 더 빠름)

(분산이 매우 적어서 5 % 미만이므로 더 이상 여러 번의 런을 평균하지 않습니다)

참고 : 전체 모듈 최적화가 없으면 그 차이는 훨씬 덜 극적입니다. 누군가 깃발이 실제로 무엇을하는지 지적 할 수 있다면 기쁠 것입니다.


업데이트 (2016 년 5 월 7 일) :

Swift 2.2.1, Xcode 7.3에서 iPhone 6S, iOS 9.3.1에서 릴리스 빌드를 실행하면 평균 5 회 이상 실행되며 Swift Compiler 설정은 -O -whole-module-optimization다음과 같습니다.

  • class 버전은 2.159942142s 걸렸다
  • struct 버전은 5.83E-08s (37,000,000 배 더 빠름)

참고 : 누군가가 실제 시나리오에서 구조체에 하나 이상의 필드가있을 것이라고 언급 했으므로 구조체 대신 1 개가 아닌 10 개의 필드가있는 구조체 / 클래스에 대한 테스트를 추가했습니다. 놀랍게도 결과는 크게 다르지 않습니다.


원래 결과 (2014 년 6 월 1 일) :

(10이 아닌 1 필드의 구조체 / 클래스에 의존)

Swift 1.2부터 Xcode 6.3.2, iPhone 5S, iOS 8.3에서 Release 빌드 실행 중 평균 5 회 이상 실행

  • class 버전 9.788332333s 소요
  • struct 버전은 0.010532942 초 (900 배 빨라짐)

이전 결과 (알 수없는 시간부터)

(10이 아닌 1 필드의 구조체 / 클래스에 의존)

MacBook Pro에 릴리스 빌드가있는 경우 :

  • class버전은 1.10082 초 걸렸다
  • struct버전 (50 배 빠른) 0.02324 초를했다

구조체와 클래스의 유사점

간단한 예제로 이것에 대한 요점을 만들었습니다. https://github.com/objc-swift/swift-classes-vs-structures

그리고 차이점

1. 상속.

구조는 신속하게 상속받을 수 없습니다. 네가 원한다면

class Vehicle{
}

class Car : Vehicle{
}

수업에 가십시오.

2. 통과

스위프트 구조는 값으로 전달되고 클래스 인스턴스는 참조로 전달됩니다.

상황에 따른 차이

구조 상수 및 변수

예 (WWDC 2014에서 사용)

struct Point{

   var x = 0.0;
   var y = 0.0;

} 

Point라는 구조체를 정의합니다.

var point = Point(x:0.0,y:2.0)

이제 x를 변경하려고하면 유효한 표현입니다.

point.x = 5

그러나 점을 상수로 정의하면.

let point = Point(x:0.0,y:2.0)
point.x = 5 //This will give compile time error.

이 경우 전체 지점은 불변 상수입니다.

클래스 클래스를 대신 사용하면 유효한 표현식입니다. 클래스 불변 상수는 인스턴스 변수가 아닌 클래스 자체에 대한 참조이기 때문에 (변수가 상수로 정의되지 않은 경우)


고려해야 할 다른 이유는 다음과 같습니다.

  1. 구조체는 코드에서 전혀 유지 관리 할 필요가없는 자동 초기화 프로그램을 얻습니다.

    struct MorphProperty {
       var type : MorphPropertyValueType
       var key : String
       var value : AnyObject
    
       enum MorphPropertyValueType {
           case String, Int, Double
       }
     }
    
     var m = MorphProperty(type: .Int, key: "what", value: "blah")
    

클래스에서 이것을 얻으려면 초기화 프로그램을 추가하고 초기화 기를 유지해야 합니다 ...

  1. 기본 컬렉션 유형 Array은 구조체입니다. 자신의 코드에서 더 많이 사용할수록 참조가 아닌 값으로 전달하는 데 더 익숙해집니다. 예를 들어 :

    func removeLast(var array:[String]) {
       array.removeLast()
       println(array) // [one, two]
    }
    
    var someArray = ["one", "two", "three"]
    removeLast(someArray)
    println(someArray) // [one, two, three]
    
  2. 명백하게 불변성 vs. 가변성은 큰 주제이지만, 많은 똑똑한 사람들은 불변성 (이 경우 구조체)이 바람직하다고 생각합니다. 가변 대 불변 개체


우리가 Struct값 유형 이고 Class참조 유형 이라고 가정하면 .

값 유형과 참조 유형이 무엇인지 모르는 경우 참조 별 전달과 값별 전달의 차이점무엇입니까? 를 참조하십시오 .

mikeash의 게시물을 기반으로 :

... 극단적이고 명백한 예를 먼저 살펴 보겠습니다. 정수는 분명히 복사 가능합니다. 값 유형이어야합니다. 네트워크 소켓은 현명하게 복사 할 수 없습니다. 이들은 참조 유형이어야합니다. x, y 쌍과 같이 포인트를 복사 할 수 있습니다. 값 유형이어야합니다. 디스크를 나타내는 컨트롤러는 현명하게 복사 할 수 없습니다. 이것이 참조 유형이어야합니다.

일부 유형은 복사 할 수 있지만 항상 발생하지 않을 수도 있습니다. 이는 참조 유형이어야 함을 나타냅니다. 예를 들어, 화면의 버튼을 개념적으로 복사 할 수 있습니다. 사본은 원본과 동일하지 않습니다. 사본을 클릭하면 원본이 활성화되지 않습니다. 사본은 화면에서 동일한 위치를 차지하지 않습니다. 버튼을 전달하거나 새 변수에 넣으면 원래 버튼을 참조하고 명시 적으로 요청했을 때만 사본을 만들고 싶을 것입니다. 즉, 버튼 유형은 참조 유형이어야합니다.

보기 및 창 컨트롤러도 비슷한 예입니다. 아마도 복사가 가능할 수도 있지만, 당신이하고 싶은 일은 거의 없습니다. 이들은 참조 유형이어야합니다.

모델 유형은 어떻습니까? 시스템의 사용자를 나타내는 사용자 유형 또는 사용자가 수행 한 조치를 나타내는 범죄 유형이있을 수 있습니다. 이것들은 꽤 복사 가능하기 때문에 아마도 가치 유형이어야합니다. 그러나 프로그램의 한 위치에서 작성된 사용자 범죄에 대한 업데이트가 프로그램의 다른 부분에 표시되기를 원할 것입니다. 이것은 사용자가 어떤 종류의 사용자 컨트롤러로 참조 유형을 관리해야 함을 나타 냅니다. 예 :

struct User {}
class UserController {
    var users: [User]

    func add(user: User) { ... }
    func remove(userNamed: String) { ... }
    func ...
}

컬렉션은 흥미로운 경우입니다. 여기에는 문자열뿐만 아니라 배열 및 사전과 같은 것들이 포함됩니다. 복사 할 수 있습니까? 명백하게. 원하는 일을 쉽고 자주 복사하고 있습니까? 덜 명확합니다.

대부분의 언어는 이것에 "아니오"라고 말하고 컬렉션을 참조 유형으로 만듭니다. Objective-C 및 Java, Python 및 JavaScript 및 거의 모든 다른 언어에서 생각할 수 있습니다. (STL 콜렉션 유형의 C ++은 한 가지 주요 예외이지만 C ++은 모든 것을 이상하게 수행하는 언어 세계의 미치광이입니다.)

스위프트는 "예"라고 말했는데, 이는 Array와 Dictionary, String과 같은 타입이 클래스가 아닌 구조체라는 것을 의미합니다. 할당과 매개 변수로 전달할 때 복사됩니다. 사본이 싸기 만하면 Swift가 달성하기 위해 매우 열심히 노력하는 한 이것은 전적으로 합리적인 선택입니다. ...

또한 함수의 모든 인스턴스를 재정의해야 할 때, 즉 공유 기능 이없는 클래스를 사용하지 마십시오 .

따라서 클래스의 여러 하위 클래스를 갖는 대신. 프로토콜에 맞는 여러 구조체를 사용하십시오.


몇 가지 장점 :

  • 공유 할 수 없어서 자동으로 스레드 세이프
  • isa 및 refcount가 없기 때문에 적은 메모리 사용
  • 메소드는 항상 정적으로 전달되므로 인라인 될 수 있습니다 (@final은 클래스에 대해이 작업을 수행 할 수 있지만)
  • 스레드 안전성과 같은 이유로 추론하기 쉬움

구조는 클래스보다 훨씬 빠릅니다. 또한 상속이 필요한 경우 클래스를 사용해야합니다. 가장 중요한 점은 클래스는 참조 유형이고 구조는 값 유형입니다. 예를 들어

class Flight {
    var id:Int?
    var description:String?
    var destination:String?
    var airlines:String?
    init(){
        id = 100
        description = "first ever flight of Virgin Airlines"
        destination = "london"
        airlines = "Virgin Airlines"
    } 
}

struct Flight2 {
    var id:Int
    var description:String
    var destination:String
    var airlines:String  
}

이제 둘 다의 인스턴스를 만들 수 있습니다.

var flightA = Flight()

var flightB = Flight2.init(id: 100, description:"first ever flight of Virgin Airlines", destination:"london" , airlines:"Virgin Airlines" )

이제이 인스턴스를 id, description, destination 등을 수정하는 두 함수에 전달할 수 있습니다.

func modifyFlight(flight:Flight) -> Void {
    flight.id = 200
    flight.description = "second flight of Virgin Airlines"
    flight.destination = "new york"
    flight.airlines = "Virgin Airlines"
}

또한,

func modifyFlight2(flight2: Flight2) -> Void {
    var passedFlight = flight2
    passedFlight.id = 200
    passedFlight.description = "second flight from virgin airlines" 
}

그래서,

modifyFlight(flight: flightA)
modifyFlight2(flight2: flightB)

이제 flightA의 ID와 설명을 인쇄하면

id = 200
description = "second flight of Virgin Airlines"

여기서, modify 메소드에 전달 된 매개 변수가 실제로 flightA 객체 (참조 유형)의 메모리 주소를 가리 키기 때문에 FlightA의 id와 설명이 변경되었음을 알 수 있습니다.

이제 FLightB 인스턴스의 ID와 설명을 인쇄하면

id = 100
description = "first ever flight of Virgin Airlines"

여기서는 modifyFlight2 메소드에서 Flight2의 실제 인스턴스가 참조 (값 유형)가 아닌 전달이기 때문에 FlightB 인스턴스가 변경되지 않았 음을 알 수 있습니다.


Structs있습니다 value typeClasses입니다reference type

  • 값 유형이 참조 유형보다 빠릅니다.
  • 여러 스레드가 경쟁 조건이나 교착 상태에 대해 걱정할 필요없이 인스턴스를 변경할 수 있으므로 값 유형 인스턴스는 다중 스레드 환경에서 안전합니다.
  • 값 유형에는 참조 유형과 달리 참조가 없습니다. 따라서 메모리 누수가 없습니다.

다음과 value같은 경우 유형을 사용하십시오 .

  • 사본이 독립적 인 상태를 갖기를 원하면 데이터가 여러 스레드에서 코드로 사용됩니다.

다음과 reference같은 경우 유형을 사용하십시오 .

  • 공유 가능한 변경 가능 상태를 작성하려고합니다.

추가 정보는 Apple 문서에서도 찾을 수 있습니다

https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html


추가 정보

신속한 가치 유형은 스택에 유지됩니다. 프로세스에서 각 스레드에는 고유 한 스택 공간이 있으므로 다른 스레드는 값 유형에 직접 액세스 할 수 없습니다. 따라서 경쟁 조건, 잠금, 교착 상태 또는 관련 스레드 동기화 복잡성이 없습니다.

값 유형은 동적 메모리 할당 또는 참조 카운팅이 필요하지 않으며 둘 다 비싼 작업입니다. 동시에 값 형식의 메서드는 정적으로 전달됩니다. 이는 성능 측면에서 가치 유형에 유리하게 큰 이점을 제공합니다.

여기에 스위프트 목록이 있습니다.

값 유형 :

  • 구조
  • 열거 형
  • 튜플
  • 프리미티브 (Int, Double, Bool 등)
  • 컬렉션 (배열, 문자열, 사전, 세트)

참조 유형 :

  • 수업
  • NSObject에서 오는 것
  • 함수
  • 폐쇄

이 Apple 블로그 게시물 에서 값 유형과 참조 유형의 관점에서 질문에 대답하면 매우 간단하게 나타납니다.

다음과 같은 경우에 값 유형 [예 : struct, enum]을 사용하십시오.

  • ==로 인스턴스 데이터를 비교하는 것이 의미가 있습니다.
  • 사본이 독립적 인 상태를 갖기를 원합니다
  • 데이터는 여러 스레드에서 코드로 사용됩니다

다음과 같은 경우 참조 유형 [예 : 클래스]을 사용하십시오.

  • ===와 인스턴스 ID를 비교하는 것이 합리적입니다.
  • 공유 가능한 변경 가능한 상태를 만들려고합니다.

이 기사에서 언급했듯이 쓰기 가능한 속성이없는 클래스는 구조체와 동일하게 작동하지만 한 가지주의 사항이 있습니다. 구조는 스레드 안전 모델에 가장 적합 합니다 . 이는 현대 앱 아키텍처에서 점점 더 요구되는 요구 사항입니다.


클래스를 사용하면 상속을 받고 참조로 전달되며, 구조체에는 상속이 없으며 값으로 전달됩니다.

Swift에는 훌륭한 WWDC 세션이 있으며이 특정 질문은 그 중 하나에서 자세히 설명됩니다. 언어 가이드 나 iBook보다 훨씬 빠르게 속도를 높일 수 있으므로 시청하십시오.


구조체가 기능을 덜 제공한다고 말하고 싶지는 않습니다.

물론, 돌연변이 기능을 제외하고는 자기 자신은 변하지 않지만 그게 전부입니다.

상속은 모든 클래스가 추상적이거나 최종적이어야한다는 오래된 아이디어를 고수하는 한 잘 작동합니다.

프로토콜로 추상 클래스를 구현하고 구조체로 최종 클래스를 구현하십시오.

structs의 좋은 점은 copy on write가 처리하기 때문에 공유 가능한 변경 가능한 상태를 만들지 않고 필드를 변경할 수 있다는 것입니다. :)

그렇기 때문에 다음 예제의 속성 / 필드가 모두 변경 가능한 이유는 Java 또는 C # 또는 빠른 클래스 에서는 수행하지 않는 것입니다 .

"example"이라는 함수의 맨 아래에 약간 더럽고 간단한 사용법이있는 상속 구조 예제 :

protocol EventVisitor
{
    func visit(event: TimeEvent)
    func visit(event: StatusEvent)
}

protocol Event
{
    var ts: Int64 { get set }

    func accept(visitor: EventVisitor)
}

struct TimeEvent : Event
{
    var ts: Int64
    var time: Int64

    func accept(visitor: EventVisitor)
    {
        visitor.visit(self)
    }
}

protocol StatusEventVisitor
{
    func visit(event: StatusLostStatusEvent)
    func visit(event: StatusChangedStatusEvent)
}

protocol StatusEvent : Event
{
    var deviceId: Int64 { get set }

    func accept(visitor: StatusEventVisitor)
}

struct StatusLostStatusEvent : StatusEvent
{
    var ts: Int64
    var deviceId: Int64
    var reason: String

    func accept(visitor: EventVisitor)
    {
        visitor.visit(self)
    }

    func accept(visitor: StatusEventVisitor)
    {
        visitor.visit(self)
    }
}

struct StatusChangedStatusEvent : StatusEvent
{
    var ts: Int64
    var deviceId: Int64
    var newStatus: UInt32
    var oldStatus: UInt32

    func accept(visitor: EventVisitor)
    {
        visitor.visit(self)
    }

    func accept(visitor: StatusEventVisitor)
    {
        visitor.visit(self)
    }
}

func readEvent(fd: Int) -> Event
{
    return TimeEvent(ts: 123, time: 56789)
}

func example()
{
    class Visitor : EventVisitor
    {
        var status: UInt32 = 3;

        func visit(event: TimeEvent)
        {
            print("A time event: \(event)")
        }

        func visit(event: StatusEvent)
        {
            print("A status event: \(event)")

            if let change = event as? StatusChangedStatusEvent
            {
                status = change.newStatus
            }
        }
    }

    let visitor = Visitor()

    readEvent(1).accept(visitor)

    print("status: \(visitor.status)")
}

Swift에서는 프로토콜 지향 프로그래밍이라는 새로운 프로그래밍 패턴이 도입되었습니다.

창조 패턴 :

Struct는 신속하게 자동 복제되는 값 유형 입니다. 따라서 프로토 타입 패턴을 무료로 구현하는 데 필요한 동작을 얻습니다.

반면 클래스를 자동으로 할당하는 동안 복제되지 않은 참조 형이다. 프로토 타입 패턴을 구현하려면 클래스가 NSCopying프로토콜을 채택해야 합니다.


얕은 사본 은 참조 만 복제하고, 해당 오브젝트를 가리키는 반면, 깊은 사본은 오브젝트의 참조를 복제합니다.


참조 유형 에 대해 딥 카피구현 하는 것은 지루한 작업이되었습니다. 클래스에 추가 참조 유형이 포함 된 경우 각 참조 특성에 대해 프로토 타입 패턴을 구현해야합니다. 그런 다음 프로토콜 을 구현하여 실제로 전체 객체 그래프를 복사해야 합니다.NSCopying

class Contact{
  var firstName:String
  var lastName:String
  var workAddress:Address // Reference type
}

class Address{
   var street:String
   ...
} 

structs와 enums 를 사용 하면 복사 로직을 구현할 필요가 없으므로 코드가 더 단순 해졌습니다.


많은 Cocoa API에는 NSObject 서브 클래스가 필요하므로 클래스를 사용해야합니다. 그러나 그 외에 Apple의 Swift 블로그에서 다음 사례를 사용하여 struct / enum 값 유형을 사용할지 클래스 참조 유형을 사용할지 결정할 수 있습니다.

https://developer.apple.com/swift/blog/?id=10


이 답변에주의를 기울이지 않는 한 가지 점은 클래스 대 구조체를 보유하는 변수는 let여전히 객체의 속성을 변경할 수 있지만 구조체로는이를 수행 할 수 없다는 것입니다.

이것은 변수가 다른 객체를 가리 키지 않고 객체를 수정해야하는 경우에 유용합니다. 예를 들어, 여러 인스턴스 변수를 차례대로 업데이트하려는 경우에 유용합니다. 구조체 인 경우 varSwift의 상수 값 유형은 제로 돌연변이를 적절하게 허용하지만 참조 유형 (클래스)은 이러한 방식으로 작동하지 않으므로 변수를 다른 객체로 재설정하여 이를 수행해야합니다.


구조체는 값 유형이므로 스택에 저장하는 메모리를 매우 쉽게 만들 수 있습니다. 스트럭처는 쉽게 액세스 할 수 있으며 작업 범위 후에 스택 상단에서 팝을 통해 스택 메모리에서 쉽게 할당 해제됩니다. 반면에 클래스는 힙에 저장하는 참조 유형이며 한 클래스 객체의 변경 사항은 단단히 결합되고 참조 유형이므로 다른 객체에 영향을 미칩니다. 구조의 모든 멤버는 공용이지만 클래스의 모든 멤버는 비공개입니다 .

구조체의 단점은 상속 될 수 없다는 것입니다.


  • 구조와 클래스는 사용자 정의 데이터 형식입니다

  • 기본적으로 구조는 공용이지만 클래스는 비공개입니다

  • 클래스는 캡슐화의 원리를 구현

  • 클래스의 객체는 힙 메모리에 생성됩니다

  • 클래스는 재사용 성을 위해 사용되는 반면, 구조는 동일한 구조로 데이터를 그룹화하는 데 사용됩니다

  • 구조 데이터 멤버는 직접 초기화 할 수 없지만 구조 외부에서 할당 할 수 있습니다.

  • 클래스 데이터 멤버는 덜 매개 변수 생성자에 의해 직접 초기화되고 매개 변수화 된 생성자에 의해 지정 될 수 있습니다

참고 URL : https://stackoverflow.com/questions/24232799/why-choose-struct-over-class

반응형