메서드
메서드는 간단하게 말하면 특정 구조체에서 사용할 수 있는 함수라고 볼 수 있다. 메서드는 함수와 동일하게 fn
으로 정의하고, 매개변수와 결과값도 지정한다. 다만 메서드는 일반 함수를 정의할 때와 달리 impl
블록 안에 함수들을 정의해야 한다는 점과 첫 번쨰 매개변수로 &self
를 넣어야 한다는 점이 있다. 메서드 예시 코드를 보면서 좀 더 알아보자.
1 | struct Rectangle { |
위 코드는 사각형의 면적을 구하는 프로그램을 작성한 것이다. 메서드를 정의하기 위해서는 impl
뒤에 구조체 이름을 붙이면 된다. 위 구조는 impl
컨텍스트 내부에 정의되는 모든 함수들을 Rectangle
의 메서드로 사용하겠다는 의미를 가진다. 정의한 메서드를 사용하는 방식은 해당 구조체 인스턴스 다음에 마침표, 메서드의 이름, 괄호 순서로 작성하면 된다.area()
라는 메서드의 매개변수는 Rectangle
이 아닌 self
를 사용한다. 이 또한 이미 area()
가 Rectangle
의 컨텍스트 내부에 정의됨으로서 해당 구조체의 메서드라는 것을 러스트가 알고 있기애 굳이 다시 데이터 타입을 알려줄 필요가 없다는 것을 의미한다.
위 코드는 area()
가 Rectangle
필드 값을 참조만 하면 되기에 &self
을 사용하였다. 상황에 따라서 self
또한 가변변수로 대여하거나 소유권을 가져오는 등의 설정도 가능하다.
많은 매개변수를 가진 메서드
이제 메서드에 대해 기본적인 구조는 배웠다. 이를 바탕으로 아래의 문제를 풀어보자.
1 | // Q: 아래의 코드에서 compare()을 작성하여 프로그램을 완성해보자. |
위 문제를 해결하기 위해서는 rec1.compare(&rec2)
에 해당하는 함수가 필요하다. compare()
은 예측했겠지만 Rectangle
의 메서드이다. 제대로 작동하는 메서드 코드를 작성했다면 결과는 아래과 같다.
1 | rec1은 rec2를 가릴 수 있나요? false |
위 문제는 rec1
이 나머지 사각형을 가릴 수 있는지 여부를 판단하는 것이었다. 즉, 가로, 세로 모든 면적이 다른 사각형보다 길거나 같아야지만 가릴 수 있다. 따라서 rec1은 rec2보다 width가 짧기에 가릴 수 없으며 정답은 false
이며, rec3와 비교했을 때 rec1 모든 변의 길이가 같거나 더 길기에 정답은 true
이다. 위 문제를 해결하는 코드는 다양하겠지만 아래의 코드는 위 설명을 그대로 구현하였다.
1 | struct Rectangle { |
이제 코드의 관점으로 되돌아오자. 위 코드는 메서드로 compare()
을 구현하였으며, 매개변수를 2개 사용하여 두 개의 사각형 정보를 입력하였다. 첫번째 매개변수의 경우 해당 메서드를 사용할 인스턴스의 값이기에 &self
로 작성하였으며, 두번째의 경우는 어떤 데이터가 들어오는지 타입을 명확히 지정해주었다. 위 예시로 알 수 있듯이 매서드를 불러오는 인스턴스만 &self
그 뒤에 추가적으로 필요한 매개변수는 함수와 동일하게 작성하면 된다.
연관 함수
연관 함수란 해당 구조체 인스턴스를 매개변수로 사용하지는 않지만 프로그램 상 연관되어있는 함수들을 칭한다. 따라서 연관 함수는 메서드에 속하지 않는다. 다만 연관성을 나타내기 위해 impl
블록에 묶어서 정의할 수 있다. 연관 함수를 사용하는 방법은 impl이름::함수이름()
구조이며, 보통 해당 구조체 인스턴스를 리턴하는 생성자를 구현해야 할 때 자주 사용된다.
1 | struct Rectangle { |
위 코드는 squre()
이라는 연관함수를 통해 Rectangle
의 인스턴스를 생성하고 이에 대한 면적을 구하는 코드이다. 이와 같이 연관 함수는 메서드는 아니지만 impl
블록 내에서 정의되는 메서드와 연관이 있는 경우 메서드와 같이 블록 내부에 정의한다.
여러 개의 impl 블록
특정 구조체에 하나의 impl
블록만을 정의할 수 있는 것은 아니다. 상황에 따라서 블록을 구분하는게 코드가 더 명확할 때가 있기에 충분히 여러 개로 나누어 사용할 수 있다.
1 | struct Rectangle { |
위 코드는 연관 함수와 메서드를 impl
블록으로 나누어 작성하였다. 물론 예시처럼 간단한 코드들은 하나의 impl
블록에 써도 상관없지만 가능하다는 것을 보기 위해 나눈 것일 뿐 어떤 규칙은 없다.