Swift 문법 CH.7

김성환·2020년 9월 6일
0

swift문법

목록 보기
10/11

안녕하세요. 본 포스트에서는 Swift의 열거형과 익스텐션에 대해 설명하겠습니다.

※ 참고자료 : 꼼꼼한 재은 씨의 Swift:문법편

목차

  • 1. 열거형
  • 2. 익스텐션

1. 열거형

열거형이란?

하나의 주제로 연관된 데이터들이 멤버로 구성되어 있는 자료형 객체
즉, 클래스,구조체와 같이 데이터 타입이다.

열거형 vs 집단 자료형

  • 집단 자료형의 특징
    1.정의된 것이 아니라 할당된 것이다. 즉, 할당된 값 자체를 타입으로 사용 불가능함
    2.정의할 때 값이 함께 정의되는 것이 아니다.(초기화 필수) 즉, 컴파일러가 안의 값을 미리 인지할 수 없다.
  • 열거형의 특징
    1.열거형 객체를 정의하는 시점에 함께 정의가 됨. 즉, 컴파일러가 안의 값을 미리 인지할 수도 있다.
    2.열거형의 데이터를 함부로 삭제하거나 변경할 수 없다.(할당된 것이 아니라 정의된 것이기 때문)

즉, 열거형을 이용해 데이터 타입을 정의하고 사용하면 컴파일러가 오류를 바로 찾아내 수정할 수 있지만, 집단 자료형을 사용하여 데이터 타입을 사용하면 잘못 사용했을 경우 실행 도중 오류를 발견하기 때문에 안정성이 떨어진다.

열거형을 사용하는 이유

  • 값의 범위를 제한하고, 무작위로 값이 입력되는 것을 방지해 코드의 안전성을 높임
  • 입력값의 오류를 줄임

열거형을 사용하는 경우

  • 원치 않는 값이 잘못 입력되는 것을 막고 싶을 때
  • 입력받은 값을 미리 특정할 수 있을 때
  • 제한된 값 중에서만 선택할 수 있도록 강제하고 싶을 때

열거형의 정의

enum 키워드와 case키워드를 사용해 정의한다.

enum 열거형 이름{
    //열거형의 멤버 정의
    case 멤버값
    case 멤버값
    ....
}

예시를 통해 살펴보자

enum Direction{
    case north
    case south
    case west, east // 1개의 case에 여러개를 넣어도 된다.
    //case를 사용하는 것은 가독성 때문이다.
}
let N = Direction.north
let S : Direction = .south // 타입이 지정되었을 경우 값을 .데이터 로 받을 수 있다.
let W : Direction = Direction.west
var E = Direction.west // E의 경우 타입이 정해짐 따라서 값을 바꾸려면
E = .east // 이것도 가능하다.
E = Directiom.east // 이것도 가능하고
// N,S,W,E는 모두 열거형으로 정의된 Direction타입이다.

열거형 타입의 데이터를 참조할 경우 .(점)을 이용하면 된다.

열거형의 멤버와 값의 분리

열거형에 멤버만 넣고 그 멤버 자체를 값으로 사용할 수 있지만 그 멤버에 데이터 값을 넣어줄 수도 있다.
즉, 멤버 자체로도 값으로 사용이 가능하고 그 멤버안에 들어간 데이터 값을 사용할 수 있다는 뜻이다.
이때, 열거형 멤버에 대입할 타입을 어노테이션으로 명시하지 않을 경우 값을 넣어줄 수 없다.
멤버에 값을 넣을 경우 반드시 어노테이션을 이용해 타입을 명시해야 한다.

enum 열거형 이름 : 멤버에 대입할 타입{
    //열거형의 멤버 정의
    case 멤버값 =case 멤버값 =....
}

이때, 정수형(Int)의 경우 값을 생략하면 맨위의 case부터 0부터 1씩 증가되는 값이 들어간다.
또한 문자열의 경우 값을 생략하면 멤버 자체의 값이 곧 멤버에 들어간 값이 된다.
그렇다면 멤버 자체의 값과 멤버 안에 들어간 값을 어떻게 구분해 사용할까?
멤버 안에 들어간 값을 사용할 경우 rawValue 라는 키워드를 사용한다.
이때, 멤버에 들어갈 타입이 명시되어 있지 않을 경우에 rawValue를 사용할 경우 오류 발생한다.

enum Direction{
    case north
    case south 
    case west, east 
}
enum Direction1: Int{
    case north // 0이 들어감
    case south // 1이 들어감
    case west, east // 2,3이 각각 들어감
}
enum Direction2: Int{
    case north = 4
    case south // 맨위가 4부터 시작이니 1증가인 5가 들어감
    case west, east // 6,7이 들어감
}
let S : Direction1 = .south
let S1 : Direction1 = .south
let S2 : Direction2 = .south
// print(S.rawValue) -> 오류!!
print(S1.rawValue)
print(S2.rawValue)
// 실행결과
1
5

열거형의 프로퍼티와 메소드

열거형도 하나의 타입이기 때문에 연산프로퍼티와 메소드를 정의할 수 있다.
하지만 위에서도 설명했듯 열거형은 할당이 아니라 정의가 된 것이기 때문에 인스턴스를 만들수 없다. 이것이 클래스,구조체와의 큰 차이점이다.
즉, 정의된 것을 인스턴스처럼 사용한다는 것이다.
아래는 예시이다.

enum HTTPCode : Int{
    case OK = 200
    case NOT_MODIFY = 304
    case INCORRECT_PAGE = 404
    case SERVER_ERROR = 500
    var value: String{
        return "HTTPCode number is \(self.rawValue)"
    }
    func getDescription() -> String {
        switch self {
            case .OK :
                return "응답이 성공했습니다. HTTP 코드는 \(self.rawValue)입니다."
            case .NOT_MODIFY :
                return "변경된 내역이 없습니다. HTTP 코드는 \(self.rawValue)입니다."
            case .INCORRECT_PAGE :
                return "존재하지 않는 페이지입니다. HTTP 코드는 \(self.rawValue)입니다."
            case .SERVER_ERROR :
                return "서버 오류입니다. HTTP 코드는 \(self.rawValue)입니다."
        }
    }
    static func getName() -> String{
        return "This Enumeration is HTTPCode"
    }
}
var response = HTTPCode.OK // response에 OK대입
// 위 문장이 클래스와 구조체와의 다른점이다. 즉, 인스턴스 생성 없이 사용가능!
response = .NOT_MODIFY // response에 NOT_MODIFY 대입
print(response.value) // response가 가진 value값을 출력
print(response.getDescription()) // response가 가진 getDescription함수를 호출
print(HTTPCode.getName()) // HTTPCode가 가진 타입 메소드 호출
// 실행결과
HTTPCode number is 304
변경된 내역이 없습니다. HTTP 코드는 304입니다.
This Enumeration is HTTPCode

위의 코드를 살펴보면, HTTPCode의 타입의 멤버타입은 정수형이다.
또한 HTTPCode는 함수 2개를 갖는데 getDescription함수는 현재 값이 OK, NOT_MODIFY, INCORRECT_PAGE, SERVER_ERROR에 따라 다른 문자열을 출력하는 함수이다.
getName함수는 타입 메소드이므로 직접 사용이 가능하다.
마지막으로 연산 프로퍼티인 value의 경우 자신의 멤버자체 값에 따라 갖는 값이 다르다.

2. 익스텐션

익스텐션이란?

확장구문, 즉, 이미 존재하는 클래스나 구조체, 열거형 등의 객체에 새로운 기능을 추가하여 확장해주는 구문이다.
즉, 새로운 객체를 정의하는 것이 아니라 이미 존재하는 객체에 여러가지 요소를 추가해주는 것이다.

  • 익스텐션은 extension 이라는 키워드를 사용해 구현한다.
extension 확장할 기존의 객체이름 {
   //추가할 기능에 대한 구현 코드 작성
}

익스텐션을 사용하는 이유

  • 라이브러리, 프레임워크에 포함되어 소스에 직접 접근할 수 없는 객체를 익스텐션을 이용해 새로운 기능을 추가해 사용가능

익스텐션으로 구현 가능한 것들(대표적인것들)

  • 새로운 연산 프로퍼티 추가
  • 새로운 메소드 정의
  • 새로운 초기화 구문
  • 기존 객체 수정하지 않고 프로토콜 구현 가능(다음쳅터에 소개함)

주의 오버라이딩은 안된다.

아래는 각종 예시들

extension Double{ // 기존에 있는 Double 구조체를 확장함
   var km: Double { return self * 1000.0}
   var m: Double { return self}
   var cm: Double { return self / 100.0}
   var mm: Double { return self / 1000.0}
   var description : String{
       return "\(self)km는 \(self.km)m, \(self)cm는 \(self.cm)m이다."
   }
   func printOrigin(){
       print("현재 값은 \(self)입니다.")
   }
}
print(2.km)
print(5.5.cm)
print(7.0.description)
66.0.printOrigin()
// 실행결과
2000.0
0.055
7.0km는 7000.0m, 7.0cm는 0.07m이다.
현재 값은 66.0입니다.
profile
개발자가 되고 싶다

0개의 댓글