[Swift] Operator Method (연산자 메소드)

Geon·2022년 8월 3일

Swift 기초

목록 보기
6/10
post-thumbnail

Operator Overloading

연산자 메소드는 기존에 존재하는 연산자의 쓰임을 확장시키는 것으로, 'Operator Overloading (연산자 오버로딩)' 이라고 하기도 한다.

struct Point{
	var x = 0.0
    var y = 0.0
}

let pointA = Point(x:10, y:20)
let pointB = Point(x:25, y:40)

x 좌표값과 y 좌표값을 가지고 있는 Point라는 구조체를 생성하고 (구조체는 나중에 포스팅으로 다루겠다. 지금은 그냥 변수나 함수등을 세트로 사용할수 있게 해주는 묶음 정도의 느낌으로만 이해해두자.), pointA와 pointB에 각각 다른 좌표값을 넣어 상수를 선언해주었다.

pointA == pointB //error!

여기서 우리가 사용하는 == 연산자를 통해 pointA==pointB 로 둘의 x와 y의 좌표값이 모두 같은지 비교하려 하면 에러가 발생한다. 기본적인 == 연산자에는 우리가 좌표로 설정한 x와 y를 함께 비교하는 기능이 구현되어 있지 않기 때문이다.

이러한 상황에서 우리는 아래와 같이 연산자 메소드를 통한 연산자 오버로딩으로 이를 해결할 수 있다.

extension Point : Equatable {//비교하는 메소드가 필요하기에 Equatable 프로토콜에 속한 비교메소드를 사용
    static func == (lp : Point, rp : Point) -> Bool {
        return (lp.x == rp.x) && (lp.y == rp.y)
    }
}

p1 == p2 //false
p1 != p2 //true   -> !=는 구현 안했지만 ==의 반대이기에 시스템에서 알아서 계산해준다.

연산자 메소드는 위와 같이 보통 extension으로 시작한다.
또한 어떤 데이터의 값의 동등한지를 판단하기 위해선 해당 데이터의 타입이 Equatable 프로토콜을 채택하고 있어야 한다. (참고 : 애플 개발자 문서 - Equatable)
위의 코드에선 Point라는 이름의 구조체가 Equatable 프로토콜을 채택하여 동등한지를 판단할 수 있게 해준 뒤, 두 Point 구조체의 x 좌표값과 y 좌표값이 동등한지 판단할 수 있도록 구현한 모습이다.

Unary Operator Overloading

이번엔 연산자가 피연산자 앞이나 뒤에 붙는 단항 연산자를 오버로딩 하는 방법이다. 피연산자 앞에 붙는 전위 연산자를 구현해보자.

extension Point {
    static prefix func -(pt: Point) -> Point { //단항 연산자를 구현할 땐 이 연산자가 어디에 위치할건지 선언해줘야 하는데 음수로 바꾸는 연산자기에 피연산자 앞에 위치 -> prefix
        return Point(x: -pt.x, y: -pt.y)
    }
}
let p3 = -p1
p3.x //-10
p3.y //-20

위는 Point 구조체의 x, y 좌표값을 음수로 바꾸는 연산자 메소드이다. 음수로 바꿔주려면 좌표값 앞에 - 기호가 붙어야 하니 prefix 를 써주고, 각 값 앞에 -가 붙어서 리턴되도록 메소드를 구현해 주었다.



이번엔 연산자가 피연산자 뒤에 붙는 후위 연산자를 구현해 보겠다.

extension Point {
    static postfix func ++(pt: inout Point) -> Point{ //후위 증가 연산자니까 postfix, 연산 도중에 파라미터 값이 바뀌기 때문에 inout으로 파라미터 설정
        let result = pt
        pt.x += 1
        pt.y += 1
        return result
    }
}


var p4 = Point(x:1.0,y:2.0)
var p5 = p4++

p5.x //1
p5.y //2

p4.x //2
p4.y //3

각 좌표값에 후위 증가가 되도록 postfix로 선언하여 메소드를 구현해준 모습이다.
괄호 안에 파라미터를 넣는 부분에 inout 을 사용했는데, 나중에 배울 내용이지만 간단히 설명하면 아래와 같다.

Inout

Swift에서 함수의 파라미터는 상수(Constant)이므로 함수 내부에서 파라미터의 값을 변경할 수 없다. 만약 함수에서 파라미터의 값을 변경하고, 그 변경된 값이 함수 호출이 종료된 후에도 지속되길 원할 때 inout 파라미터를 사용한다

우리가 구현하려는 각 좌표값을 1씩 증가시키는 후위 연산자는 Point 구조체의 x, y값을 변경시킬 것이고, 그 값을 메소드가 종료되어도 유지시킬 것이기 때문에 inout을 사용했다고 생각해두자.

inout에 대한 이해를 도울 겸 아래의 연산자 오버로딩 예시를 하나 더 구현해 보겠다.

extension Point {
    static func +=(lp: inout Point, rp : Point) -> Point {
        let result = lp
        lp.x = lp.x + rp.x
        lp.y = lp.y + rp.y
        return result
    }
}

var p6 = Point(x:2,y:2)
p6 += p1
print(p6) //Point(x: 14.0, y: 36.0)

왼쪽에 좌표값에 오른쪽의 좌표값을 더하는 += 연산자를 오버로딩 하였다. 여기서 더해진 왼쪽의 값은 메소드를 나와서도 저장이 되어야 하기 때문에 inout이 첫번째 파라미터인 lp에만 붙는 것이다.

profile
별에 별 지식 저장해놓고 꺼내먹기📚

0개의 댓글