오늘은 struct와 class에 대해서 알아보자.
둘의 차이점에 초점을 맞춰서 알아보려 한다.
struct
와 class
프로그램에서 범용적이고 유연한 구조를 가진 코드 블록이다.
상수, 변수, 함수를 정의할때와 같은 구문으로 struct
와 class
에 기능을 추가하는 property와 method를 정의한다.
struct
와 class
는 프로그램을 구성하는데 필요한 블록을 만드는 용도이다.
그렇다면 struct
와 class
의 공통점과 차이점에 대해 알아보자.
struct
또는 class
property에 접근할도록 subscript 정의 가능class
의 추가 기능은 복잡성이 증가한다.
일반적으로는 추론이 쉬운 struct
를 권장하고, 필요할 때 class
를 사용하라고 한다.
위에서 struct
와 class
의 공통점과 차이점에 대해 알아봤다.
위의 차이점 말고도 struct
와 class
의 가장 큰 차이점이 있다.
struct
는 value type이고, class
는 reference type이다.
하나씩 살펴보자.
value type은 변수 또는 상수에 할당되거나 함수에 전달 될때 값이 복사되는 유형이다.
Swift의 모든 기본 유형(integers, floating-point, numbers, Booleans, strings, arrays, dictionaries)들은 value type이고, struct
로 구현되어 있다.
모든 struct
와 enum
은 Swift에서 value type이다.
즉, 코드에서 전달될 때 항상 복사된다.
Array, dictionary, string 같은 표준 라이브러리에 의해 정의된 collection은 복사 성능 비용을 줄이는 최적화를 사용한다.
이런 collection은 바로 복사본을 만드는 대신 원본 인스턴스와 복사본 간에 메모리를 공유한다.
collection의 복사본 중 하나가 수정되면 수정 직전에 요소가 복사된다.
struct Resolution {
let width: Int
let height: Int
}
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
hd
에 Resolution 인스턴스를 선언했다.
cinema
에 hd
를 선언했다.
그리고 이후에
cinema.width = 2048
cinema
의 width 값을 변경했다.
struct
는 value type으로 변수 또는 상수에 전달 될때 값이 복사된다고 했다.위의 사항을 생각하면서 코드를 다시 살펴보자.
var cinema = hd
cinema
에 hd
를 지정했으므로 cinema가 생성된다.
아직 수정이 일어나지 않았으므로 원본 인스턴스와 메모리를 공유한다.
cinema.width = 2048
cinema
의 프로퍼티 값을 변경했으므로 이제 복사본이 생성된다.
reference type은 value type과 다르게 변수 또는 상수에 할당되거나 함수에 전달될 때 복사되지 않는다.
복사본 대신 원본 인스턴스의 참조를 사용한다.
class VideoMode {
let resolution: String
let interlaced: Bool
let name: String
let frameRate: Double
}
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
tenEighty
에 VideoMode 인스턴스를 선언했다.
alsoTenEighty
에 tenEighty
를 선언하고, alsoTenEighty
의 frameRate 값을 변경했다.
VideoMode는 reference type으로 reference를 공유한다고 했다.
따라서 After 상태를 보면 tenEighty
와 alsoTenEighty
가 같은 인스턴스인 것을 확인할 수 있다.
alsoTenEighty
의 frameRate 값을 변경했지만 tenEighty
와 같은 인스턴스이기 때문에
print(tenEighty.frameRate)
를 하게되면 30.0이 출력되는 모습을 확인할 수 있다.
class
는 reference type이므로 tenEighty
와 alsoTenEighty
처럼 같은 인스턴스를 참조하고 있을 수 있다.
상수 또는 변수가 동일한 클래스 인스턴스를 참조하는지 확인하기 위한 연산자가 있다.
흐음... 딱 생긴게 위에꺼는 같은 인스턴스인지 아래는 같은 인스턴스가 아닌지를 구별하는거네...ㅋㅋㅋ
Apple에서 친절하게 가이드 해주고 있다.
struct
와 class
는 앱에서 데이터를 저장하고 동작을 모델링하는데 좋은 선택이지만 유사성으로 인해 서로를 선택하기 어려울 수 있다.
(맞아요...)
앱에 새 데이터 type을 추가할 때 적합한 옵션을 선택하려면 아래의 권장 사항을 고려해 봐라!
(네..)
struct
를 사용class
사용class
사용protocol
과 함께 struct
를 사용하나씩 살펴보자.
struct
를 사용Swift의 struct
에는 다른 언어에서는 class
에서만 사용할 수 있는 기능들을 사용할 수 있다.
Swift의 struct
는 protocol
을 채택해 기본 구현을 얻을 수 있다.
(struct
는 class
와 달리 상속 받을 순 없지만 protocol
을 채택함으로써 공통적으로 가져야 하는 구현부를 공유할 수 있다는 얘기 같음)
struct
는 value type이기 때문에 struct
의 변경은 의도적으로 다른 곳으로 전달하지 않는 한 표시되지 않는다.
(reference type인 경우 reference를 공유하기 때문에 하나가 변경되면 다른 곳의 변수 혹은 상수도 변경된다.)
따라서 struct
인스턴스 변경은 명시적으로 변경된다.
(즉, 해당 struct
인스턴스를 변경해도 다른 인스턴스에는 영향이 없다는 말)
class
사용데이터를 처리해야하는 Objective-C API를 사용하거나 Objective-C 프레임워크에 정의된 클래스에 데이터 모델을 적용해야하는 경우 class
를 사용해야 한다.
class
사용Swift의 class
는 reference type으로 ID 개념이 내장되어 있다.
두 개의 서로 다른 클래스 인스턴스가 동일한 값을 가질 때 ===(ID 연산자)로 서로 다른 인스턴스임을 알 수 있다.
class
인스턴스는 다른 상수 혹은 변수와 reference를 공유할 수 있으므로 인스턴스가 변경된다면 reference를 공유하는 모든 곳에서 변경을 알 수 있다.
protocol
과 함께 struct
를 사용struct
와 class
는 모두 상속을 지원한다.
(오잉... 우리 여태 struct
는 상속이 불가능하다고 했는데...!)
struct
는 class
를 상속할 수는 없지만 protocol
을 채택해 상속을 지원할 수 있다.
class
상속 계층 구조를 protocol
과 struct
를 사용해 모델링 할 수 있다.
(오호... 그럼 class
상속은 안되지만 protocol
을 이용해 상속 비스무리하게 할 수 있나보다!)
protocol
은 class
, struct
, enum
모두 채택할 수 있어 상속을 지원할 수 있지만, class
상속은 class
에서만 호환된다.
protocol
로 상속을 지원할 때에는 우선 protocol
상속을 통해 상속 계층을 모델링 한뒤, struct
에서 protocol
을 채택하도록 해라.
struct
와 class
를 결정하는때 Apple에서 제공하는 고려 사항을 알아봤다.
Apple은 다음 조건 중 하나 이상에 해당한다면 struct
를 사용하는 것을 권장한다.
struct
에 저장된 property가 value type이며 참조하는 것보다는 복사하는 것이 합당할 때 오늘은 struct
와 class
에 대해 알아봤다.
사실 깊게 들어가면 끝도 없지만...!
오늘은 이정도로 마무리!
그럼 이만👋