QA Automation/swift5

9. 구조체와 클래스

kokorii_ 2023. 6. 21. 14:00
  • 열거형, 구조체의 인스턴스는 값 타입, 클래스의 인스턴스는 참조 타입
  • 소스파일 하나에 여러개의 구조체와 여러 개의 클래스를 정의하고 구현할 수 있음

9.1 구조체

9.1.1 구조체 정의

struct 구조체 이름 { //구조체 이름은 대문자 카멜케이스 
	프로퍼티와 메소드들
}
  • 예시
strcut BasicInformation {
	var name: String
	var age: Int
}

9.1.2 구조체 인스턴스의 생성 및 초기화

  • 초기화 시 기본적으로 생성되는 멤버 와이즈 이니셜라이저를 사용
  • 사용자 정의 이니셜라이저도 구현 가능
var personInfo: BasicInformation = BasicInformation(name: "blair", age: 99)
personInfo.age = 100
personInfo.name = "seba"

let sebaInfo: BasicInformation = BasicInformation(name: "Seba", age: 22)
// 프로퍼티 변경 불가 

9.2 클래스

9.2.1 클래스 정의

객체를 인스턴스화하기 전에 먼저 객체에 대한 '청사진'인 클래스를 정의해야 한다. 

class 클래스 이름 {
	프로퍼티와 메서드들
}
  • 상속을 받을 경우
class 클래스 이름: 부모 클래스 이름 {
	프로퍼티와 메서드들
}
  • 저장프로퍼티가 있는 클래스의 예시
class Person {
	var height: Float = 0.0
	var weight: Float = 0.0
}

9.2.2 클래스 인스턴스의 생성과 초기화

  • 클래스의 생성
    • 위 작업은 클래스에 대한 구조 정의이며, 클래스를 이용하여 어떤 작업을 하려면 클래스의 인스턴스를 생성해야 한다. 
    • 인스턴스에 대한 참조체를 저장할 변수를 선언해서 인스턴스를 생성한다. 
  • 클래스의 초기화  
    • 초기화 시 기본 이니셜라이저 init 메서드 사용
    • 사용자가 직접 이니셜라이저 정의 가능
  • 객체는 클래스의 인스턴스이다. 
var yagom: Person = Person()
yagom.height = 123.4
yagom.weight = 123.4

9.2.3 클래스 인스턴스의 소멸

  • 스위프트 런타임 시스템에 의해 클래스 인스턴스가 없어지기 전에 해야 할 정리 작업은 클래스 안에 소멸자를 구현하면된다. 
  • 클래스의 인스턴스(객체)는 참조 타입이므로 더 참조할 필요가 없을 때 메모리에서 해제됨.
  • deinit : 디이니셜라이저, 클래스 소멸 전 호출됨
    • 클래스당 하나만 구현 가능
    • 매개변수와 반환값을 가질 수 없음
  • 인스턴스 소멸 전에 데이터를 저장하거나 다른 객체에 인스턴스 소멸을 알려야 할 때 deinit 메서드를 구현함

9.3 구조체와 클래스의 차이

같은점

  • 프로퍼티 정의 가능
  • 메서드 정의 가능
  • 서브스크립트 문법을 통해 프로퍼티에 접근
  • 초기화 시 이니셜라이저 정의 가능
  • 익스텐션을 통한 확장
  • 프로토콜 준수

다른점

  • 상속은 클래스만 가능
  • 타입캐스팅은 클래스의 인스턴스에만 허용
  • 디이니셜라이저는 클래스의 인스턴스에만 가능
  • 참조 횟수 계산은 클래스의 인스턴스에만 가능

두 타입의 가장 큰 차이점은 구조체는 값타입, 클래스는 참조 타입이라는 점

9.3.1 값 타입과 참조 타입

  • 값타입 : 어떤 함수의 전달인자로 값 타입의 값을 넘긴다면 전달될 값이 복사되어 전달 됨
  • 참조타입: 참조 타입이 전달인자로 전달될 때는 주소가 전달됨 (포인터와 유사한 개념)
  • 중요 예제 코드!
struct BasicInformation {
  let name: String
  var age: Int
}

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

var friendInfo: BasicInformation = yagomInfo

print("yagom's age: \\(yagomInfo.age)")
print("friend's age: \\(friendInfo.age)")

friendInfo.age = 999

print("yagom's age: \\(yagomInfo.age)")
print("friend's age: \\(friendInfo.age)")

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

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

print("yagom's height : \\(yagom.height)")
print("friend's height: \\(friend.height)")

friend.height = 185
print("yagom's height: \\(yagom.height)")
print("friend's height: \\(friend.height)")

func changeBasicInfo(_ info: BasicInformation){
  
  var copy: BasicInformation = info
  copy.age = 1
}

func changePersonInfo(_ info: Person){
  
  info.height =  153
}

changeBasicInfo(yagomInfo)
print("yagom's age: \\(yagomInfo.age)")

changePersonInfo(yagom)
print("yagom's height: \\(yagom.height)")
  • 값 타입의 데이터를 함수의 전달인자로 전달하면 메모리에 전달인자를 위한 인스턴스가 새로 생성되고, 이 새로 생성된 인스턴스에 전달하려는 값이 복사되어 들어감
  • 참조 타입의 데이터는 기존 인스턴스의 참조를 전달하므로 기존 인스턴스 참조를 전달

식별연산자

  • 클래스의 인스턴스끼리 참조가 같은지 확인하는 방법
var yagom: Person = Person()
let friend: Person = yagom
let another: Person = Person()

print(yagom === friend)
print(yagom === another)
print(friend !== another)

9.3.2 스위프트의 기본 데이터 타입은 모두 구조체

  • 스위프트의 기본 타입은 모두 구조체로 구현되어 있음
  • String 타입의 기본 정의
public struct String {
	public init()
}

9.4 구조체와 클래스 선택해서 사용하기

애플의 가이드라인에서 다음 조건 중 하나 이상에 해당한다면 구조체를 사용할 것을 권장

  • 연관된 간단한 값의 집합을 캡슐화하는 것만이 목적일 때
  • 캡슐화한 값을 참조하는 것보다 복사하는 것이 합당할 때
  • 구조체에 저장된 프로퍼티가 값 타입이며 참조하는 것보다 복사하는 것이 합당할 때
  • 다른 타입으로부터 상속받거나 자신을 상속할 필요가 없을 때

구조체로 사용하기에 가장 적합한 예는 좌표계