[Swift] 구조체와 클래스

사실 좀 현생이 바빠서 취미로 계속 하던 iOS, Swift를 조금 놓고 있었던게 사실이다.
이왕 하기로 한거 좀 더 제대로 깊이 있게 하고싶어서 다시 기본기부터 손을 대기로했다.

야곰님의 스위프트 프로그래밍을 짬짬이 읽으면서 공부 한 것들 중 좀 기억해야하고 중요하다고 생각되는 것들을 정리해서 올려보려고 한다.

Summary

구조체

  • value 타입
    - 참조 횟수 계산이 필요 없다(ARC에 의해 메모리 해제되지 않음)
  • struct 키워드 사용
  • Extension 위해 새로운 기능 추가로 확장 가능
  • 서브스크립트로 구조체 프로퍼티에 접근 가능

클래스

  • reference 타입
    - 참조 횟수 계산이 필요 하다(ARC에 의해 메모리 해제 됨)
    • 순환 참조에 의한 참조 관계 정리 필요
  • class 키워드 사용
  • Extension 사용 가능
  • 타입 캐스팅 가능
  • deinit으로 해제 가능

구조체

Swift에서 구조체는 struct 키워드를 통해 정의한다.

struct 구조체이름 {
	프로퍼티 & 메소드
}

간단히 책에 나오는 구조체 정의 예제를 보면 다음과 같이 표현이 된다.

struct BaisicInformation {
	var name: String
    var age: Int
}

이 구조체는

  • String 타입에 해당하는 name
  • Int 타입에 해당하는 age

라는 프로퍼티를 보유하고있다.

구조체의 정의는 굉장히 단순하다.

그래서 이것을 어떻게 사용할것인지에 대한 설명이 필요한데, 그래서 다음에 볼것이 "구조체" 인스턴스의 생성 및 초기화를 볼것이다.

구조체 정의를 마치면 인스턴스를 생성하고 초기화할때는 기본적으로 멤버 와이즈 이니셜라이저를 사용한다.(참고로 Class에선 멤버 와이즈 이니셜라이저를 제공하지 않음ㅎㅎ) 구조체에 기본 생성된 이니셜라이저의 매개변수들은 구조체의 프로퍼티 네임을 바탕으로 자동 지정된다.

var yagomInfo : BaisicInformation = BaisicInformation(name: "yagom", age: 99)
yagomInfo.age = 100
yagomInfo.name = "seba"

인스턴스가 생성되고 초기화 된 이후에 프로퍼티에 접근하고 싶다면 마침표를 통해 접근이 가능하다.

클래스

스위프트에서 클래스는 부모 클래스가 없더라도 상속없이 단독으로 정의가 가능하다.

정의할때는 class 키워드를 사용한다.

class 이름{
	프로퍼티들
}

클래스 정의하는 방법을 보아 하니 위에 구조체랑 굉장히 흡사하다.
하지만 클래스는 상속이 가능하고 상속 받을때는 클래스 이름 뒤에 콜론을 통해 부모 클래스의 이름을 명시해줘야 한다.

class 클래스 이름: 부모 클래스 이름 {
	프로퍼티, 메소드 들
}

클래스를 정의 한 후, 인스턴스를 생성하고자 할 때는 기본적인 이니셜라이저를 사용한다.

class Person {
	var height: Float = 0.0
    var weight: Float = 0.0
}

예를들어 Person 클래스에서는 프로퍼티 기본값이 저장이 되어있어서 따로 초기 값을 전달해줄 필요는 없다.

인스턴스가 생성되고 초기화 된 이후(이니셜라이즈 이후) 프로퍼티 값에 접근하고자 한다면 마찬가지로 마침표를 사용해서 접근이 가능하다.

클래스 인스턴스의 소멸

클래스의 인스턴스는 Reference 타입에 해당한다.
참조할 필요가 없을 경우에는 메모리에서 해제되어야 할텐데, 이를 소멸이라고 한다.
소멸 되기 직전에 클래스는 deinit이라는 메소드가 호출된다.
이렇게 호출되는 deinit은 클래스당 하나만 구현 가능하고, 매개변수와 반환 값을 가지게 된다.

class Person {
	var height: Float = 0.0
    var weight: Float = 0.0
    
    deinit {
    	print("Person 클래스의 인스턴스 소멸.")
	}
}

var yagom: Person? = Person()
yagom = nil // => Person 클래스의 인스턴스 소멸. 메세지 출력

보통 deinit 메소드 에는 인스턴스가 메모리에서 해제 되기 직전에 처리해야할 코드들을 넣어준다.
예를들어서 인스턴스 소멸 전에 데이터를 저장하거나 다른 객체에 인스턴스 소멸을 알려야 할 경우에 말이다.

스위프트에서 구조체와 클래스의 차이

공통점

  • 값을 저장하기 위한 프로퍼티를 정의하고 사용할 수 있다.
  • 기능 실행을 위한 메소드를 정의할수 있다.
  • 서브스크립트 문법을 통해서 구조체나 클래스가 갖는 값에 접근하도록 서브스크립트를 정의할수 있다.
  • 초기화 될 때 상태를 지정하기 위해 이니셜라이저를 정의할수 있다.
  • 초기 구현과 더불어 새로운 기능 추가를 위해 익스텐션을 통해서 확장이 된다.
  • 특정 기능을 실행하기 위해서 특정 프로토콜들을 준수할수 있다.

차이점

  • 구조체는 상속이 불가능하다.
  • 타입캐스팅은 클래스의 인스턴스만 허용이 된다.
  • 디이니셜라이저는 클래스의 인스턴스에서만 사용이 가능하다.
  • 참조 횟수 계산은 클래스의 인스턴스에만 적용이 된다.

사실 이렇게 장황하게 썻지만 클래스와 구조체의 가장 큰 차이점은 타입이라고 볼수 있겠다

  • 구조체 - 값 타입
  • 클래스 - 참조 타입

이런식으로 정의가 된다.

그래서 그게 값인지 참조형인지 뭐가 차이가 나는지 알아보자.

이 두가지의 가장 큰 차이점은 무엇이 어떻게 전달이 되는가다.
예를 들어서 함수 의 전달인자로 "값 타입""값"을 넘긴다면 전달될 값이 "복사" 되어 전달 된다.
반면 참조 타입은 값을 복사하지않고 참조가 전달이된다.

참조타입은 값이 복사가 되지 않고 참조가 전달되는 만큼 인스턴스 끼리의 값 비교보다는 참조 비교를 해야 할 경우가 생기는데, 이때 식별 연산자를 사용할수 있다.

var yagom: Person = Person()
let friend: Person = yagom
let anotherFriend: Person = Person()

print(yagom === friend) // true
print(yagom === anotherFriend) // false
print(friend !== anotherFriend)  // false

좋은 웹페이지 즐겨찾기