[Swift] Class and Structure 클래스와 구조체

Byunghoon Lee·2021년 7월 30일
1

iOS

목록 보기
7/11
post-thumbnail

클래스와 구조체

클래스와 구조체는 프로그램의 코드를 조직화 하기 위해 일반적으로 사용합니다.

클래스와 구조체의 비교

프로퍼티: 구조체(타입) 안에들어있는 변수
메서드: 구조체(타입) 안에들어있는 함수

공통점

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

클래스만 가능한 기능

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

구조체(Struct)는 다른 코드로 전달될 때 항상 복사되서 전달 되고, 참조 카운트(Reference counting)를 사용하지 않습니다.

선언

새로운 클래스나 구조체를 선언할 때마다 Swift에선 완전 새로운 타입을 선언하는 것이므로, 이름을 선언할땐 UpperCamelCase로 (SomeClass, SomeStructure),
프로퍼티나 메소드는 lowerCamelCase(frameRate 등)으로 선언합니다.

struct SomeStructure {
	코드작성
}

class SomeClass {
	코드작성
}

예시

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

class VideoMode {
    var resolution = Resolution() // 위 Resolution 구조체를 값으로 사용
    var interlaced = false
    var frameRate = 0.0
    var name: String?
}

구조체 Resolution의 프로퍼티 widthheight
초기 값으로 0을 할당 했기 때문에
Swift의 타입추론에 의해 자동으로 Int 형을 갖게 됩니다.

인스턴스

클래스와 구조체 이름 뒤에 빈 괄호 ()를 적으면 각각의 인스턴스를 생성할 수 있습니다.

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

구조체와 열거형은 값 타입

함수에서 상수나 변수에 전달될 때 그 값이 복사되서 전달 된다는 의미입니다.

예제를 보면,

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

cinemahd 는 아래와 같이 값을 복사만 하기 때문에 서로 완전히 다른 인스턴스 입니다.

print(cinema)  // Resolution(width: 2048, height: 1080)
print(hd)      // Resolution(width: 1920, height: 1080)

클래스는 참조 타입

참조 타입은 변수나 상수에 값을 할당 하거나 함수에 인자로 전달할 때 그 값이 복사되지 않고 참조 됩니다.

참조된다 : 그 값을 갖고 있는 메모리를 바라보고 있음. (예제 참고)

예제를 보면,

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

print(tenEighty.frameRate) // 25.0

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30

let alsoTenEighty2 = alsoTenEighty
alsoTenEighty.frameRate = 40
print(tenEighty.frameRate)  // 40
print(alsoTenEighty.frameRate)  // 40

왜 40 ?

위처럼 alsoTenEighty2 상수가 alsoTenEighty 인스턴스를 복사한 것이 아니라 참조한 것이기 때문입니다.
alsoTenEightytenEighty 가 바라보고 있는 메모리 주소를 동일하게 바라보고 참조하고 있는 것입니다.

한가지 더, 아래처럼 상수로 선언 했는데 값이 변경되었는지!?

let alsoTenEighty2 = alsoTenEighty

-> alsoTenEighty2 자체를 변경하는게 아니라 그것이 바라보는 을 변경하는 것이기 때문에 가능합니다.

식별 연산자 (Identity Operators)

클래스는 참조 타입 이기 때문에 여러 상수와 변수에서 같은 인스턴스를 참조할 수 있습니다. 상수와 변수가 같은 인스턴스를 참조하고 있는지 비교하기 위해 식별 연산자 를 사용합니다.

  • ===: 두 상수나 변수가 같은 인스턴스를 참조하고 있는경우 true
  • !==: 두 상수나 변수가 다른 인스턴스를 참조하고 있는경우 true

식별연산자(===)와 비교연산자(==)는 다릅니다.
식별연산자는 참조 를 비교하고,
비교연산자는 을 비교합니다.

클래스와 구조체의 선택

구조체는 이러한 조건에서 사용합니다.

  • 연관된 간단한 값을 캡슐화 하기 위한 것인 경우
  • 인스턴스가 복사 되기를 기대하는 경우
  • 구조체에 의해 저장된 프로퍼티가 복사되기를 기대하는 경우
  • 구조체가 프로퍼티나 메소드 등을 상속할 필요가 없는 경우

이 외의 경우에는 클래스를 사용합니다.

참조: 스위프트 classes & structures

profile
Never never never give up!

0개의 댓글