[Swift5] Structures and Classes 2

Junyoung Park·2022년 3월 14일
0

Swift5 Docs

목록 보기
20/37
post-thumbnail

Structures and Classes

값 타입인 구조체와 열거형

값 타입은 변수나 상수에 값을 할당하거나 함수에 전달될 때 값이 복사되는 타입이다. 스위프트의 기본적인 정수, 실수, 불리언, 문자열, 배열, 딕셔너리는 모두 값 타입이다. 구조체 및 열거형 또한 값 타입으로, 인스턴스를 코드로 전달할 때 내부 값이 복사된다.

배열, 딕셔너리, 문자열 등 컬렉션 타입은 복사 오버헤드를 줄이기 위한 최적화 기법을 사용한다. 즉각 모든 값을 복사하는 게 아니라, 원본 인스턴스와 복사본 사이에 값을 담아두는 메모리를 공유한다.

컬렉션의 복사본 중 하나의 값이 바뀌면 값을 바꾸기 직전에 원소가 복사되는 형식이다. 따라서 사용자가 보기에 값은 즉각 복사되지만, 코드 내부에서는 값이 바뀔 때까지 일부를 공유하면서 메모리 사용을 최적화한다.

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

hd 상수에 Resolution 구조체 인스턴스가 할당되고 다시 hdcinema 변수에 할당된다. cinema 변수 할당 시 인스턴스 복사본이 만들어지고, 이 새로운 복사본이 cinema 변수에 할당된다. 같은 값을 가지고 있지만 값 타입이기 때문에 서로 다른 인스턴스다.

cinema.width = 2048

print("cinema is now \(cinema.width) pixels wide")
// Prints "cinema is now 2048 pixels wide"

print("hd is still \(hd.width) pixels wide")
// Prints "hd is still 1920 pixels wide"

cinema 프로퍼티에 새로운 값을 할당, 즉 값을 수정한 뒤 cinemahd 값을 확인해보면 수정한 변수 cinema만 바뀐 것을 알 수 있다.

열거형 역시 구조체와 마찬가지로 값 할당 시 새로운 인스턴스가 만들어진다.

enum CompassPoint {
    case north, south, east, west
    mutating func turnNorth() {
        self = .north
    }
}
var currentDirection = CompassPoint.west
let rememberedDirection = currentDirection
currentDirection.turnNorth()

print("The current direction is \(currentDirection)")
print("The remembered direction is \(rememberedDirection)")
// Prints "The current direction is north"
// Prints "The remembered direction is west"

currentDirection.west 열거 타입을 할당받았지만, turnNorth() 메소드를 통해 값이 바뀐 뒤에는 currentDirectionrememberedDirection 값이 다름을 알 수 있다.

파이썬 등 배열이 참조 타입인 프로그래밍 언어의 경우 깊은 복사, 슬라이싱 등을 활용하지 않으면 값을 할당한 뒤 수정이 웡본에도 반영이 되지만, 스위프트는 값 타입이기 때문에 서로 다른 인스턴스다.

참조 타입인 클래스

반면 참조 타입인 클래스는 값이 할당될 때 복사되지 않는다. 즉 같은 인스턴스를 가리키고 있다.

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

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0

print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
// Prints "The frameRate property of tenEighty is now 30.0"

VideoMode() 클래스를 할당한 tenEighty를 할당한 alsoTenEighty에 있는 frameRate 프로퍼티 값을 alsoTenEighty에서 바꾸자. 같은 인스턴스이기 때문에 바뀐 값을 확인할 수 있다.

구조체와 달리 클래스는 참조 타입이기 때문에 소스코드 상 같은 인스턴스를 참조하고 있는 코드가 서로 떨어져서 사용되면 사용하기 불편할 수도 있다는 점에서 스위프트 문서 측에서는 구조체 사용을 권하고 있는 것 같다.

식별 연산자

참조 타입을 할당받은 상수 및 변수가 같은 인스턴스를 가리키는지 확인하기 위해 식별 연산자 ===를 사용할 수 있다.

if tenEighty === alsoTenEighty {
    print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")
}
// Prints "tenEighty and alsoTenEighty refer to the same VideoMode instance."

===를 통해 같은 인스터스라면 true를 리턴한다. 반대는 !== 연산자다.

포인터

C 등 언어의 포인터는 메모리 주소를 참조한다. 스위프트 또한 메모리 참조가 가능하지만 직접적인 주소를 가리키거나 *를 붙이지 않아도 된다는 점에서 다르다.

profile
JUST DO IT

0개의 댓글