🍏 4. 사용자 정의 자료형 (User-Defined Types)
사용자 정의 자료형 = Stored Property : 저장 프로퍼티
프로퍼티 관련 게시물은
👆 클릭하여 링크로 이동하여 자세히 확인 가능
◻️ 1) 구조체 (Struct)
- CLASS와 다르게 상속이 불가능 합니다.
- (인스턴스/타입)메서드, (인스턴스/타입)프로퍼티 (클래스와 같음)
- 값타입(=value type) (value 라고 부름)
- Swift의 대부분의 큰 뼈대는 모두 STRUCT(구조체)로 구성이 되어있습니다.
- Int, Double, String 등 데이터 타입 값 타입을 정의하는 자료형, 변수나 상수에 할당되거나 함수에 인자로 전달될 때 복사됨
- init()을 생성하지 않아도 됨.
struct 구조체이름 {
}
struct Point {
var x: Int
var y: Int
}
- 구조체는 다른 구조체를 속성으로 가질 수 있음
struct Size {
var width: Double
var height: Double
}
struct Position {
var x: Double
var y: Double
}
struct Rectangle {
var size: Size
var position: Position
}
let size = Size(width: 100.0, height: 50.0)
let position = Position(x: 10.0, y: 20.0)
let rectangle = Rectangle(size: size, position: position)
print("Rectangle size: \(rectangle.size.width) x \(rectangle.size.height)")
print("Rectangle position: (\(rectangle.position.x), \(rectangle.position.y))")
🍀① Struct 인스턴스 생성 및 초기화
- 구조체를 정의하고 인스턴스를 생성하고 초기화 할때는 멤버와이즈 이니셜라이저를 사용합니다. 구조체의 프로퍼티 이름으로 자동으로 지정됩니다.
- 만약 인스턴스가 생성되고 초기화된 후에 프로퍼티 값에 접근하려면 마침표를 사용하면 됩니다.
struct Point {
var x: Int
var y: Int
}
let point = Point(x: 10, y: 20)
print("Point: (\(point.x), \(point.y))")
🍀② Struct의 장점
- 속도 : 값 타입은 시스템 리소스를 적게 먹음
- 안전성 : 클래스는 참조 타입이기 때문에 '원본'에 바로 접근이 가능하지만, 구조체는 원본은 그대로 두고 복사가 일어나기 때문에 원본을 지킬 수 있음. 클래스보다 안전한 코딩이 가능함. 여러 클래스 또는 다중 스레드 환경에서 변수를 전달할 때 유용, 변수의 복사본을 다른 곳으로 보낼 수 있으면 다른 곳에서 변숫값을 변경하는 것에 대해 걱정할 필요가 없음.
- 구조체의 주요 목적은 비교적 간단한 데이터 값을 캡슐화하는 것
🍀③ Struct는 그럼 언제 써야 해?
- 참조가 아닌 복사를 원할 때
- 자신을 상속할 필요가 없거나 자신이 다른 타입을 상속받을 필요가 없을 때
- 연관된 몇몇의 값들을 모아서 하나의 데이터 타입으로 표현하고 싶을 때
but 이때는 클래스를 써야만 해!! 이때는 구조체만 써! 딱 이런 기준은 없다!!!
🌈 swift 언어 가이드 기준
- 구조체의 주목적이 몇몇 연관성 있는 간단한 데이터 값의 캡슐화일 경우
- 캡슐화 된 값들이 그 구조체의 인스턴스가 할당될 때나 전달될 때 참조보다는 복사가 예상될 경우
- 구조체에 저장되는 모든 프로퍼티들이 참조보다는 복사가 예상되는 값 형식일 경우
- 구조체가 다른 형(type)에서부터 프로퍼티나 기능이 상속될 필요가 없을 경우
🌈 Struct를 사용하는 좋은 예
- Double형을 갖는 width와 height 프로퍼티의 캡슐화를 하는 기하학적 모형의 사이즈.
- Int형을 갖는 start와 length 프로퍼티의 캡슐화를 하는 시리즈의 범위에 접근하는 방법.
- Double형을 갖는 x, y와 z 프로퍼티의 캡 슈화를 하는 3차원 좌표 시스템의 포인터.
이외의 경우에는 클래스로 정의하며, 레퍼런스로 전달되고 관리되는 클래스의 인스턴스를 생성하시면 됩니다.
실질적으로는 대부분의 사용자 데이터 형은 구조체가 아닌 클래스로 정의되어야 합니다.
◻️ 2) 클래스 (Class)
- swift에서는 객체라는 용어 대신에 인스턴스 라는 용어를 사용합니다. 한마디로 클래스 타입의 인스턴스를 객체라고 칭하지 않습니다.
- 단일 상속만 가능합니다.
- (인스턴스/타입) 메서드, (인스턴스/타입) 프로퍼티 (Struct와 같음)
- 참조타입(=reference type) (리퍼런스reference 라고 부름)
- iOS 프레임워크의 대부분이 클래스로 구성되어있습니다.
- SwiftUI에서는 대부분잉 Struct로 구성되어있습니다.
- init()을 생성해야 함.
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
🍀① Class의 정의
🌈 키워드 Class
class 클래스 이름 {
}
🌈 Class 인스턴스의 생성과 초기화
- 클래스를 정의하고 초기화 할때는 따로 초깃값을 주지 않고 이니셜라이저를 사용하면 됩니다.
- 인스턴스가 생성되고 초기화 즉, 이니셜라이즈된 후에 구조체와 마찬가지로 마침표를 사용하면 되는데, 차이점은 struct는 변수일때만 수정이 가능했지만, class는 var 이건 let이건 내부 프로퍼티 값을 변경할 수 있습니다,
◻️ 3) Class 와 Struct
🍀① Class 와 Struct의 공통점
- 서로 다른 타입(자료형)들을 하나로 묶을 수 있다.
- (인스턴스/타입) 메서드, (인스턴스/타입) 프로퍼티
- 이러한 묶은 자료형들을 새로운 타입처럼 사용 가능.
- 클래스/구조체 안에서 함수/프로퍼티 정의 가능
- extension이 가능.
🍀② Class 와 Struct의 차이점
- 클래스는 참조(Reference) 타입, 열거형과 구조체는 값(Value) 타입이라는 것이 가장 큰 차이
- 클래스는 상속(Subclassing)이 가능하지만, 열거형과 구조체는 상속이 불가능
값 타임 과 참조 타입의 가장 큰 차이점은 ' 무엇이 전달되느냐 ' 입니다.
- 값 타입(구조체) : 값 타입 데이터 -> 함수의 전달인자로 전달 -> 인스턴스 생성됨 -> 복사되어 들어감
- 참조 타입(클래스) : 참조타입 데이터 -> 기존 인스턴스의 참조를 전달
💡 대부분의 Swift 개발자는 가능하면 클래스보다 구조체를 사용하는 것을 선호💡
- 클래스에는 합성된 memberwise 이니셜 라이저가 제공되지 않습니다.
- 한 클래스는 다른 클래스 위에 빌드("상속")하여 프로퍼티와 메서드를 얻을 수 있습니다.
- 구조체의 복사본은 항상 고유 한 반면 클래스 복사본은 실제로 동일한 공유 데이터를 가리 킵니다.
- 클래스에는 클래스의 인스턴스가 소멸될 때 호출되는 메서드 인 deinitializer 가 있지만 구조체는 그렇지 않습니다.
- 상수 클래스의 변수 속성은 자유롭게 수정할 수 있지만 상수 구조체의 변수 속성은 수정할 수 없습니다.
즉, 구조체 대신 클래스를 선택할 때 위의 동작 중 하나를 원하기 때문에 그렇게 하는 것입니다
◻️ 4) 열거형 (Enum)
- 열거형은 관련된 값들을 그룹으로 묶어서 나타내는 자료형입니다.
- 배열이나 딕셔너리 같은 타입과는 다르게 프로그래머가 정의해준 항목 값 외에는 추가/수정이 불가능합니다. 그렇기 때문에 딱 정해진 값만 열거형 값에 속할 수 있습니다.
enum CompassPoint {
case north, south, east, west
}
🍀① 키워드 Enum
let result = "failure"
let result2 = "failed"
let result3 = "fail"
위의 세가지 result는 모두 다른 문자열 = 서로 다른 코드
Enum을 사용하여 수정되지 못하게 result값 정하기 가능
enum Result {
case success
case failure
}
이제 Result를 사용할 때는 두 값(success, failure)중 하나를 선택해야 합니다.
let result4 = Result.failure
🍀② Enum 사용 예시
🌈Enum을 사용하기 좋은 예시
- 방향 (동쪽, 서쪽, 남쪽, 북쪽 등)
- 오류 유형
- 영화 장르
- 요일(일주일에 7일만 있으므로)
🌈Enum을 사용하기 안 좋은 예시
- 내가 방문한 도시 목록 (이것은 배열로 작성하는 것이 좋습니다)
- 이메일 주소(String으로 작성하는 것이 좋습니다)
- 학생들의 평균 점수(Double로 작성하는것이 좋습니다)
🌈 열거형은 다음 같은 경우에 요긴하게 사용
- 제한된 선택지를 주고 싶을 때
- 정해진 값 외에는 입력받고 싶지 않을 때
- 예상된 입력 값이 한정되어 있을 때
🌈 Enum associated values (연관 값)
- Enum의 가장 강력한 기능 중 하나는 하나 이상의 관련 값, 즉 Enum case를 더 자세히 설명해주는 추가 정보를 저장할 수 있는 기능입니다.
- 연관 값은 각 항목 옆에 소괄호로 묶어 표현
- 다른 항목이 연관 값을 같는다고 모든 항목이 연관 값을 가질 필요 X
- 열거 형에 추가 정보를 첨부하여 더 세부적인 데이터를 나타낼 수 O
🌈 Enum raw values (원시 값)
- 값을 열거형에 할당하여 의미를 가질 수 있어야 함
enum Planet: Int {
case mercury
case venus
case earth
case mars
}
let earth = Planet(rawValue: 2)
enum Planet: Int {
case mercury = 1
case venus
case earth
case mars
}
let earth = Planet(rawValue: 3)
- 각 case에 값을 제공할 수 있다.
- Int raw value는 자동으로 0부터 계산된다.
- raw value는 전적으로 선택 사항이기 때문에 필수적이지 않다.
- raw value에 정수와 같은 다른 것을 사용할 수 있다.
- raw value를 사용하면 열거형 값을 동적으로 만들 수 있다.
🌈 Enum 항목 순회프로토콜 CaseIterable
프로토콜 공부 후 추가하기!