[Swift] playground를 이용해 계산기를 만들어보자 (Lv.2 까지)

sonny·2024년 10월 29일
5

TIL

목록 보기
25/48

오늘 swift 문법 종합반 1주차 강의를 듣고 계산기를 만들어보는 과제가 있다.

앞서 배운 문법 내용들을 활용하여 만들어야하는데, 레벨 1~4 까지 있지만 레벨 3까지는 필수이고.. 레벨 4는 할 수 있다면 해보는 것으로 선택할 수 있다.


Lv. 1

  • 더하기( + ), 빼기( - ), 나누기( / ), 곱하기( * ) 연산을 수행할 수 있는 calculator 클래스를 만들고 해당 클래스를 이용해 연산을 진행하고 출력해보는 것.

Lv. 2

  • 레벨1 에서 만든 calcylator 클래스에 나머지 연산 코드를 추가하고 출력까지 해보기.

Lv. 3

  1. 아래의 각 클래스를 만들고 클래스간에 관계를 고려하여 calculator 클래스와 관계 맺기.
  • AddOperation (더하기)
  • SubstractOperation (빼기)
  • MultiplyOperation (곱하기)
  • DivideOperation (나누기)
  1. calculator 클래스 내부코드를 변경하기
  2. 관계를 맺고 별도로 만든 연산 클래스의 인스턴스를 calculator 내부에서 사용하기
  • 레벨2 와 비교해서 어떤 점이 개선되었는지 스스로 생각해보기. 힌트는 클래스의 책임(단일책임원칙)

Lv. 4

  1. AbstractOperation 이라는 추상화 된 클래스를 만들기
  2. 기존에 구현한 AddOperation (더하기), SubstractOperation (빼기), MultiplyOperation (곱하기), DivideOperation (나누기) 클래스들과 관계를 맺고 Calculator 클래스의 내부 코드를 변경하기
  3. Swift의 어떤 문법을 이용해서 추상화 할 수 있는지 생각해보기
  • 레벨 3과 비교해서 어떤점이 개선되었는지 스스로 생각해 보기

자 우선 .. 연산자를 문자열로 직접 입력하는대신 enum 으로 정의를 하면 잘못된 연산자를 사용하려는 실수를 방지할 수 있다고 힌트를 얻었다.

enum 을 사용하면 연산자가 Operator 타입으로 제한되기에 문자열이 아니라서 잘못된 연산자를 사용할 가능성도 낮아지고, 오타로 인한 오류도 방지할 수 있는 1석2조다.

무엇보다 계산기를 만들 땐 switch 문이 필요한데, 이 switch 문과 enum 은 함께 사용할 때 그 진가를 발휘한다고 전에 글을 쓴 것이 기억이 났다. 각 케이스마다 별도로 처리할 수 있으니 코드의 흐름도 명확하게 만들어줄 것이다.

아 그리고 이건 처음 안건데, calculate 의 매개변수로 operation 이라고 적었는데 원래는 operator 로 적었더니 오류가 났었다.

Swift에서는 operator예약어로 지정되어 있다보니, 이름이나 함수 매개변수로 사용할 수 없다고 한다. 그래서 operation 으로 바꾼 것이다.

예약어란?
Swift 언어 내에서 특정 기능을 수행하기 위해 미리 지정된 단어들을 말하며, operator는 Swift에서 연산자 관련 기능에 사용되기 때문에 사용자 정의 변수나 매개변수 이름으로 사용할 수 없다.


1차 문제 : 함수 값 반환

잘 쓰고 있는데 갑자기 피가 났다.

계산기를 만들 때 나누기 부분에서 0 으로 나눌 수 없는 부분을 코드로 작성하던 중인데, 그냥 return 만 쓰면 될 줄 알았는데...

해석해보니 보이드가 아닌 함수는 값을 반환해야한다고 하는데.. 오류 메세지를 그대로 구글링해보니 해결방법이 그냥 return0 만 붙이면 된다고 한다.

해결

너무 간단한데 왜 붙여야하는지 이해가 되지 않아서 알아보니.. 나누기 연산을 수행할 수 없는 경우에 대해 함수가 정상적으로 값을 반환할 수 있도록 하기 위함인데,

여기서 secondNum0 일 때는 나누기를 할 수 없으므로 함수는 0을 반환하여 결과를 일관성 있게 유지해야 하기 때문이라고 한다.


2차 문제 : 나머지 연산자

나머지 연산자 공식을 써도 피가 났다.

해석해보니 '%' 사용할 수 없습니다: 부동 소수점 번호의 경우 트렁킹Remainder instea를 사용합니다 라는데, 오류메세지를 검색하니 바로 나왔다.

해결

% 연산자는 Int 에만 정의가 되어 있어 Double 에서는 사용이 불가능 했던 것이다. 그래서 다음과 같이 정의되어 있는 함수를 사용해주면 모듈로 연산자와 동일하게 사용이 가능하다

.truncatingRemainder(dividingBy:)


적용하니 깔끔해진 코드.

이렇게 적고나서 나는 초기화를 진행해줘야한다고 생각해서 init을 쓰려고 했는데 이 코드는 굳이 초기화 구문을 사용하지 않아도 된다고 한다.

친절하게도 Swift에서 모든 클래스는 프로퍼티가 없는 경우 또는 모든 프로퍼티에 기본값이 있는 경우에 자동으로 기본 초기화 구문을 제공한다고 한다.

이 기본 초기화 구문은 모든 프로퍼티가 기본값을 갖는 경우에 사용된다는 것이다.

현재 나의 Calculator 클래스는 프로퍼티가 없기 때문에 (변수나 상수가 없음), Swift는 기본 초기화 구문을 자동으로 제공해준다. 그러므로 별도로 init 을 정의할 필요가 없다는 것.

classinit 은 짝꿍인 줄로만 알았는데 처음 알았다.

예시)

class Calculator {
    var result: Double

    init() {
        result = 0
    }

    func calculate(operation: Operator, firstNum: Double, secondNum: Double) -> Double {
        // 계산 로직
    }
}

이렇게 class 밑에 result 라는 프로퍼티가 있으면 초기화 구문을 통해서 초기화 해줘야하지만 내 코드에선 따로 프로퍼티를 명시하지 않았다.

밑에 저렇게 주석처리로 메모를 한 건, 내가 인스턴스 생성에 대한 구조 이해를 하지 못해서 친절한 에밀리님에게 물어보고 적은 것이다.

let calculator = Calculator() 이걸 하는 이유가 뭔지 궁금했고, 처음엔 init 대신 해주는건가? 했는데 아예 다른 개념이었다는 걸 알게됐다.

설명을 듣고 다시 공부해보니, 이렇다.

Calculator()Calculator 클래스의 기본 초기화 구문을 호출하여 새로운 인스턴스를 생성하고, 이 인스턴스는 calculator 라는 상수에 할당되며, 이후 이 변수를 통해 Calculator 클래스의 메서드와 속성에 접근할 수 있게 해주는 것이라는 것...!

이렇게 인스턴스를 생성함으로써, 이제 calculator 변수를 사용하여 Calculator 클래스의 calculate 메서드를 호출할 수 있게 된다.

값도 의도한대로 잘 나왔고 0으로 나눌 수 없는 부분도 출력이 잘 되었다.

일단 오늘은 Lv.2 까지만 진행하고 마무리..!


음...

오늘은 클래스를 정의하고 사용하여 계산기를 구현하는 과정을 통해 여러 가지 개념을 배우게 된 듯 하다.

가장 먼저 클래스를 정의하고 인스턴스를 생성하는 방법을 배웠는데, Calculator라는 클래스를 만들어 사칙연산과 나머지 연산을 수행할 수 있는 기능을 구현했다.

클래스를 통해 인스턴스를 생성함으로써 해당 클래스를 활용하는 방법도 익혔다. let calculator = Calculator() 구문을 통해 인스턴스를 생성하고, 이 인스턴스를 사용하여 계산 기능을 활용할 수 있다는 점을 이제야 좀 알게 된 것 같다.

그리고 확실히 enum을 사용하니, 각 연산자를 명확하게 구분할 수 있어 로직이 더 직관적으로 변한 것도 있다. 나중에 계산기를 확장하거나 기능을 추가할 때 유용하게 사용할 수 있을 것 같다.

이어서 switch 문을 사용해 다양한 연산자에 대해 조건에 따라 다른 동작을 하도록 구현한 부분도 있다. 덕분에 각 연산을 간결하게 처리할 수 있고 추가로 나머지 연산자가 추가될 때의 확장성도 좋다보니 이렇게 여러 케이스를 정의하는 코드를 짤 땐 switch와 enum을 적절히 잘 사용해야겠다 싶었다.

오늘의 학습을 통해 Swift의 기본적인 문법과 객체 지향 프로그래밍의 개념을 잘 이해할 수 있었다. 계산기를 구현하는 과정에서 다양한 프로그래밍 원칙을 적용해보니, 실제 코드에서 어떻게 활용될 수 있는지를 명확히 알 수 있었다. 앞으로도 이러한 개념들을 바탕으로 더 복잡한 프로그램을 만들어 나갈 수 있도록 지속적으로 연습하고, 새로운 기능을 추가해보려 한다. 이러한 경험이 앞으로의 학습에 큰 도움이 될 것이라고 믿는다.

profile
iOS 좋아. swift 좋아.

4개의 댓글

comment-user-thumbnail
2024년 10월 29일

우와ㅏㅏ truncatingRemainder 내일 따라서 써야겠다! 인스턴스 이해를 도울 수 있어서 기뻤습니다.

1개의 답글
comment-user-thumbnail
2024년 10월 30일

멋있따 👍🏼

답글 달기
comment-user-thumbnail
2024년 10월 30일

글을 읽고나니깐 저희 사이에 벽이 느껴지네요,, 완 벽

답글 달기