아요 개발 일기

[Swift] 구조체(Struct), 클래스(Class), 열거형(Enum) 본문

Swift/Grammar

[Swift] 구조체(Struct), 클래스(Class), 열거형(Enum)

소진이 2022. 12. 30. 11:59

안녕하세요!! :D

오늘은 클래스와 구조체, 열거형에 관해 공부해보겠습니다1!!! 오늘두 화이팅!

 

상수와 변수 -> 프로퍼티(Property)

함수 -> 메소드(Method)

 


Class

  •  일반적으로 단일 상속이 가능하지만, 프로토콜을 사용하면 다중 상속도 가능
  •  참조타입 (=reference type) (call by reference)
  • 형 변환(Type Casting)과 관련된 기능과 파괴자(Deinitializer)등의 기능을 가질 수 있다.
  • iOS 프레임 워크의 대부분의 큰 뼈대는 모두 클래스로 구성
  • 메모리의 Heap 영역에 존재

 

class Helo {
    var name:String = "Sojin";
    func say(){
        print("Hello, " + name + "!");
        
    }
    
}

class Hello:Helo {
    var name2:String = "YAMADA";
    func say2(){
        print("Hi," + name + "-" + name2 + "!");
        
    }
    
}
var obj:Hello = Hello();

obj.say();
obj.name = "Sojin";
obj.name2 = "TANAKA";
obj.say2();

 

class의 자세한 내용은 Class - 클래스 포스팅을 참고해주세요

 


Struct

  • C 언어 구조체 용도와 비슷하지만, 추가로 멤버 변수(프로퍼티), 함수(메소드) 정의 가능
  • 상속이 불가능
  • 확장(extention) 등 기능 사용 가능
  • 값 타입 (= Value Type)
  • Swift의 대부분의 큰 뼈대는 모두 구조체로 구성
  • 메모리의 Stack 영역에 존재

 

struct MyData {
    var age:Int
    var name:String
    
    func getData() ->String {
        return "[\(name)(\(age))]"
        
    }
    
}

var data = MyData(age: 99, name: "Taro")
var data2 = data
data2.name = "Sojin"
data2.age = 24
print(data.getData()) // Taro(99)
print(data2.getData()) // Sojin(24)

 

Mutating function

Mutating function이란 구조체의 매서드가 구조체 내부에서 데이터를 수정할 때 선언하는 키워드입니다.

 

아래 코드를 보면서 이해해봅시다.

struct Point {
var x = 0 
var y = 0 

// 컴파일 에러남.
func moveTo(x: Int, y: Int) {
	self.x = x  
	self.y = y  
  }

// 정상 실행
mutating func moveTo2(x: Int, y: Int) {
	self.x = x  
	self.y = y  
  }
}

변수 x,y를 0으로 선언을 하였고, 그 값을 변경하려 합니다.

mutating을 선언하지 않고 내부 변수 값을 변경하면 위와 같이 컴파일 에러가 나게되니깐 꼭 붙여주세요!

 

 

Struct의 자세한 내용은 Struct - 구조체 포스팅을 참고해주세요

 

음.. 구조체를 그럼 언제 사용해야하나요?

 

 


쉽게 이야기하면, 일단 Struct로 쓰는 것이 좋다고 해요!! 

Swift에서 대부분 Struct를 사용하기도 하고, Struct를 Class로 변경하는 것도 쉽기때문이라고합니당..!!

 

 

저희 클래스와 구조체를 비교도 해볼까요?

 

클래스와 구조체의 공통점

  1. 메소드 : 함수를 사용하여 기능을 제공하는 메소드를 정의할 수 있다.
  2. 초기화 블록 : 객체를 원하는 초기 상태로 설정해주는 초기화 블록을 정의할 수 있다.
  3. 프로토콜 : 특정 형식의 함수적 표준을 제공하기 위한 프로토콜을 구현할 수 있다.
  4. 확장 : 객체에 함수적 기능을 추가하는 확장(extends) 구문을 사용할 수 있다.
  5. 서브스크립트 : 속성 값에 접근할 수 있는 방법을 제공하는 서브 스크립트를 정의할 수 있다.
  6. 프로퍼티 : 변수나 상수를 사용하여 값을 저장하는 프로퍼티를 정의할 수 있다.

 

클래스와 구조체의 차이점

  1. 구조체 value type, 클래스는 reference type 입니다.
  2. 구조체는 상속이 불가능합니다.
  3. 구조체에서는 AnyObject로 타입캐스팅이 불가능합니다.
  4. 구조체는 생성자를 구현하지 않을 시 기본 initializer를 사용할 수 있습니다.
  5. 클래스는 reference counting으로 메모리 관리가 가능합니다.

 


Enum

  •  상속 불가
  •  값 타입 (값이 없을 수도 있음. 즉 이름 그 자체 만으로 고유한 의미를 나타낼 수 있음)
  •  유사한 종류의 여러 값을 유의미한 이름으로 한 곳에 모아 정의한 것 예) 요일, 상태값, 월(Month)
  •  열거형 자체가 하나의 데이터 타입
  •  열거형의 case 하나하나 전부 하나의 유의미한 값으로 취급

 

//MARK: 열거형 사용
enum Weekday {
    case mon
    case tue
    case wed
    case thu, fri, sat, sun
}

//Weekday가 day에 타입으로 선언되어있음
//Weekday는 열거형 타입 이름.케이스 이름 으로 선언되어있음
var day: Weekday = Weekday.mon
day = .tue

print(day)

switch day { //day라는 열거형 값
case .mon, .tue, .wed, .thu:
    print("평일입니다")
case Weekday.fri:
    print("불금 파티!!")
case .sat,.sun:
    print("신나는 주말!!")
}



//MARK: - 원시값

//C언어의 enum처럼 정수값을 가질 수도 있습니다.
//rawValue를 사용하면 됩니다.
//case별로 각각 다른 값을 가져야 합니다.
//값은 자동으로 1씩 증가 한다. grape에 1을 넣지 않아도 자동으로 1이 된다.

enum Fruit: Int {
    case apple = 0
    case grape = 1
    case peach
    //case mango = 0
}

print("Fruit.peach.rawValue == \(Fruit.peach.rawValue)")
//Fruit.peach.rawValue == 2

//정수 타입 뿐만 아니라
//Hashable 프로토콜을 따르는 모든 타입이 원시값의 타입으로 지정될 수 있습니다.

enum School: String {
    case elementary = "초등"
    case middle = "중등"
    case high = "고등"
    case university
}

print("School.middle.rawValue == \(School.middle.rawValue)")
//School.middle.rawValue == 중등

print("School.university.rawValue == \(School.university.rawValue)")
//School.middle.rawValue == university - 안에 값이 없으면 case의 이름을 그대로 출력한다.



//MARK: 원시값을 통한 초기화

//rawValue를 통해 초기화 할 수 있습니다.
//rawValue가 case에 해당하지 않을 수 있으므로
//rawValue를 통해 초기화 한 인스턴스는 옵셔널 타입입니다.

//let apple: Fruit = Fruit(rawValue: 0)
let apple: Fruit? = Fruit(rawValue: 0)

if let orange: Fruit = Fruit(rawValue: 5) {
    print("rawValue 5에 해당하는 케이스는 \(orange)입니다")
} else {
    print("rawValue 5에 해당하는 케이스가 없습니다.")
} //rawValue 5에 해당하는 케이스가 없습니다.




//MARK: 메서드
enum Month {
    case dec, jan, feb
    case mar, apr, may
    case jun, jul, aug
    case sep, oct, nov

    func printMessage() {
        switch self {
        case .mar, .apr, .may:
            print("따스한 봄~")
        case .jun, .jul, .aug:
            print("여름 더워요~")
        case .sep, .oct, .nov:
            print("가을은 독서의 계절!")
        case .dec, .jan, .feb:
            print("추운 겨울입니다")
        }
    }
}

Month.mar.printMessage()

 

클래스, 구조체, 열거형에 대해서 간단하게 살펴보았는데요. 설명을 잘 했나 모르겠네요.. 

마지막으로 오늘 배운 클래스, 구조체, 열거형을 정리한 표를 보면서 마무리 하겠습니다! 오늘도 좋은 하루 보내세용 :-)

 

  Class Struct Enum
Type Reference Value Vlaue
Subclassing O X X
Extension O O O