Swift) 클래스과 구조체 (Classes and Structures)

Havi·2020년 12월 23일
0

Swift기초

목록 보기
10/19
post-custom-banner

클래스과 구조체는 코드를 조직화 하기 위해 사용한다. 이는 OOP를 위한 필수 요소이기도 하다.

클래스와 구조체의 비교 (Comparing Classes and Structures)

공통점

  • 값을 저장하기 위한 프로퍼티 정의
  • 기능을 제공하기 위한 메소드 정의
  • subscript문법을 이용해 특정 값을 접근할 수 있는 subscript정의
  • 초기 상태를 설정할 수 있는 initializer정의
  • 기본 구현에서 기능 확장
  • 특정한 종류의 표준 기능을 제공하기 위한 프로토콜 순응(conform)

차이점 (클래스에서만 가능한 기능)

  • 상속 : 클래스는 여러 속성을 다른 클래스에 물려 줌
  • 타입 캐스팅 : 런타임에 클래스 인스턴스의 타입을 확인
  • 소멸자 : 할당된 자원을 해지(free up) 시킴
  • 참조 카운트 : 클래스 인스턴스에 하나 이상의 참조가 가능

선언 문법

// 클래스나 구조체의 선언은 메소드나 프로퍼티와 달리 대문자로 시작한다.

class VideoMode {
    // class content
    var resolution = Resolution() // 아래 구조체를 값으로 사용
    var interalced = false
    var frame = 0.0
    var name: String?
}

struct Resolution {
    // struct content
    var width = 0
    var height = 0
}

클래스와 구조체 인스턴스

빈 괄호를 적으면 각각의 인스턴스를 생성

let someResolution = Resolution() // 구조체 인스턴스
let someVideoMode = VideoMode() // 클래스 인스턴스

프로퍼티 접근

dot(점) 을 통해 인스턴스의 프로퍼티에 접근 할 수 있다.

print("The width is \(someVideoMode.resolution.width)")

구조체형의 맴버 초기화

모든 구조체는 초기화시에 initializer를 자동으로 생성해 제공한다.

let vga = Resolution(width: 640, height: 480)

구조체와 열거형은 값 타입

Struct와 enum은 값 타입(Value Type)으로 상수나 변수에 전달될 때 그 값이 복사되서 전달된다.

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

이 코드에서 hdcinema는 완전히 다른 인스턴스이다.

cinema.width = 2048

print("cinema : \(cinema.width), hd: \(hd.width)")
// cinema : 2048, hd: 1920

enum 또한 마찬가지이다.

enum CompassPoint {
    case north, south, east, west
}
var currentDirection = CompassPoint.west
let rememberedDirection = currentDirection
currentDirection = .east
if rememberedDirection == .west {
    print("The remembered direction is still .west")
}
// "The remembered direction is still .west" 출력

클래스는 참조 타입

클래스 는 값 타입과 달리 변수나 상수에 값을 할당하거나 함수에 인자로 전달할 때 그 값이 복사되지 않고 참조된다.
참조된다란 그 값을 갖는 메모리를 바라보고 있다는 뜻이다.

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

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0

print("frameRate of tenEighty is now \(tenEighty.frameRate)")

식별 연산자

클래스는 참조 타입이기 때문에 같은 인스턴스를 참조하고 있는지를 비교하기 위해 다음과 같은 식별자를 사용한다.

  • === : 두 상수나 변수가 같은 인스턴스를 참조하고 있는 경우 참
  • !== : 두 상수나 변수가 다른 인스턴스를 참조하고 있는 경우 참
if tenEighty === alsoTenEighty {
print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")
}
// "tenEighty and alsoTenEighty refer to the same VideoMode instance." 출력

포인터

C, C++, Obj-C는 포인터가 실제 메로리를 가르키고 키워드로 표시하지만, Swift는 참조를 가르키기위해 사용하지 않고 변수나 상수처럼 정의해서 사용.

클래스와 구조체의 선택

다음 조건 중 1개 이상을 만족하면 구조체 사용을 고려해 볼 수 있다.

  • 구조체의 주 목적이 관계된 간단한 값을 캡슐화(encapsulate) 하기 위한 것인 경우
  • 구조체의 인스턴스가 참조되기 보다 복사되기를 기대하는 경우
  • 구조체에 의해 저장된 어떠한 프로퍼티가 참조되기 보다 복사되기를 기대하는 경우
  • 구조체가 프로퍼티나 메소드 등을 상속할 필요가 없는 경우

String, Array, Dictionary의 할당과 복사 동작

Swift에서는 String, Array, Dictionary같은 기본 데이터 타입이 Struct로 구현 돼 있다. 따라서 이 값을 할당하거나 메소드에 인자로 넘길 때는 값이 복사(Copy-on-Write)된다.

CoW 관련 짤막한 정리글

반면 FoundationNSString, NSArray등은 클래스로 구현 돼 있습니다. 따라서 이 값들은 참조가 사용됩니다.

profile
iOS Developer
post-custom-banner

0개의 댓글