객체지향 프로그래밍을 하면서, 객체들의 요소를 서로 비교하거나, 더할 때가 생긴다.
예를들면, A라는 사람과 B라는 사람을 객체로 두고, 이 사람들의 소지금을 요소라고 가정했을 때,
우리가 A의 소지금에서 B의 소지금을 빼려고 하면 A.money - B.money 와 같은 연산이 필요했다.
이런 경우에서 더 나아가, 소지금 뿐 아니라 나이, 키, 몸무게 등 여러가지 요소를 비교하거나, 더하고 빼는 등,
각 객체들의 요소를 연산하고 싶어질 때가 많으면 많을수록, 많은 연산을 반복해야한다는 번거로움이 생긴다.
또한, 이렇게 연산한 값을 가진 새로운 객체를 만들고자 한다면, 구조가 많이 복잡해질 수 있다.
이럴때, 객체들끼리 + 연산자를 통해서 서로가 가진 요소들을 더할수는 없을까?
이러한 기능을 연산자 오버로딩을 통해서 수행이 가능하다.
연산자 오버로딩은 말 그대로 우리가 사용하는 +, -, * 등 연산자에 기능을 재정의하여
사용자 정의 자료형들 끼리의 연산을 가능하게 하는 것이다.
여기서 사용자정의 자료형이란, 사용자가 직접 선언하고, 설계하고, 이용할 수 있는 클래스나 구조체등을 말한다.
그럼 이러한 연산자 오버로딩은 어떻게 하는 것인지 알아보자.
using System;
namespace Favor
{
internal class Program
{
class Point
{
int x;
int y;
public Point(int x, int y) {this.x = x; this.y = y;}
public static Point operator - (Point left, Point right)
{
return new Point(left.x - right.x, left.y - right.y);
}
}
static void Main(string[] args)
{
Point p = new Point(10, 10) - new Point(5, 3);
Console.WriteLine($"p의 x값 : {p.x}, p의 y값 : {p.y}");
// 출력값 : p의 x값 : 5, p의 y값 : 7
}
}
}
우선 사용자정의 자료형을 만들어주자. 여기서는클래스로 만들어주겠다.
그 후, 정의하고자 하는 연산자를 선언해준다. public static Point operator - 의 뜻에 대해 더 자세히 살펴보자.
사실, operator 앞의 문구들은 우리가 다 아는 내용이다.
이 연산자의 사용은 public이고 정적이며, Point객체를 반환하는 역할을 하는 것이다.
이 처럼 함수와 비슷한 선언 방식을 가지고 있는데, 그렇다면 빠진 것이 하나 있다. 바로 함수의 이름이다.
연산자 오버로딩은 쉽게 생각하면, 그냥 함수의 이름을 연산자로 설정하는 것과 비슷하다.
함수의 호출을 할 때는, 함수의 이름으로 호출했었는데, 이의 경우는 연산자를 사용하는 것으로 가능하다는 것이다.
그러나 조건이 있다. 우선, 연산자가 좌항의 값과 우항의 값을 필요로 하듯, 연산자 오버로딩에도 매개변수가 두개 필요하다.
두개 이상도 아니고 이하도 아니다. 정확히 두개가 필요하다.
이 때, 매개변수중 하나는 꼭 사용자정의 자료형을 포함하는 자료여야 한다.
쉽게 말해, Point 클래스 내부에서 Point끼리만 통하는 연산자를 정하기로 했는데, 거기에 Point가 빠질 수는 없다는 것이다.
위처럼 둘 다 Point 클래스거나, 둘 중 하나는 반드시 Point일 필요가 있다.
그런 다음, 매개 변수를 이용하여 그 두개의 객체가 연산자를 만났을 때 취할 행동을 정의하면 된다.
연산자 오버로딩의 내용은 반드시 반환값이 존재하여야 하며, void함수가 될 수는 없다.
이렇게 오버로딩한 연산자를 통해 위의 메인함수에서 새로운 객체를, 10,10에서 5,3의 값을 뺀 새 객체를 생성했다.
연산자 오버로딩은 직관성과 가독성을 크게 높일 수 있다는 장점이 있다.
클래스사이에서, 혹은 클래스와 다른 변수 사이에서 연산할 때, 번거로운 작업을 연산자 오버로딩을 통해서 가독성 좋게 만들 수 있다.
그러나 유의해야할 것은, 오버로딩 할 수 있는 연산자의 갯수가 많지 않다는 것이다.
우리는 클래스의 메서드를 무수히 많이 정의하고 사용할 수 있다. 그러나 연산자에는 정해진 갯수가 있다.
따라서, 연산자 오버로딩을 함에 있어, 꼭 연산자의 원래 기능과 유사한 기능으로 오버로딩을 해야할 필요가 있으며,
연산자의 갯수는 정해져있기 때문에 신중히 연산자를 선택해야한다.
'C# 일기' 카테고리의 다른 글
| 17. 예외처리(Exception Handling) (0) | 2024.03.11 |
|---|---|
| 16. 일반화 (Generic <T>) (0) | 2024.03.08 |
| 14. Array 클래스 (0) | 2024.03.08 |
| 13. String과 StringBuilder (2) | 2024.03.08 |
| 12. 객체지향의 특징 (0) | 2024.03.06 |