[Swift 문법] 2 - 4. 사용자 정의 자료형

JJOOEE__·2024년 6월 12일
0

Swift 문법

목록 보기
8/13
post-thumbnail

🍏 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))") // 출력: Point: (10, 20)

🍀② 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을 사용하기 좋은 예시

  1. 방향 (동쪽, 서쪽, 남쪽, 북쪽 등)
  2. 오류 유형
  3. 영화 장르
  4. 요일(일주일에 7일만 있으므로)

🌈Enum을 사용하기 안 좋은 예시

  1. 내가 방문한 도시 목록 (이것은 배열로 작성하는 것이 좋습니다)
  2. 이메일 주소(String으로 작성하는 것이 좋습니다)
  3. 학생들의 평균 점수(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)
  • 원시 값이 있는 열거형
  1. 각 case에 값을 제공할 수 있다.
  2. Int raw value는 자동으로 0부터 계산된다.
  3. raw value는 전적으로 선택 사항이기 때문에 필수적이지 않다.
  4. raw value에 정수와 같은 다른 것을 사용할 수 있다.
  5. raw value를 사용하면 열거형 값을 동적으로 만들 수 있다.

🌈 Enum 항목 순회프로토콜 CaseIterable

프로토콜 공부 후 추가하기!

profile
개발이 어려운 나를 위한... 개발노트

0개의 댓글