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 구조체와 클래스 선택해서 사용하기
애플의 가이드라인에서 다음 조건 중 하나 이상에 해당한다면 구조체를 사용할 것을 권장
- 연관된 간단한 값의 집합을 캡슐화하는 것만이 목적일 때
- 캡슐화한 값을 참조하는 것보다 복사하는 것이 합당할 때
- 구조체에 저장된 프로퍼티가 값 타입이며 참조하는 것보다 복사하는 것이 합당할 때
- 다른 타입으로부터 상속받거나 자신을 상속할 필요가 없을 때
구조체로 사용하기에 가장 적합한 예는 좌표계