매개변수가 있는 트레이트
Coddy Rust 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 61개 중 33번째.
지금까지 우리의 트레이트 메서드들은 &self만을 매개변수로 받아왔습니다. 하지만 트레이트 메서드는 일반 메서드와 마찬가지로 추가적인 매개변수를 받을 수 있으며, 이는 실제 작업에서 훨씬 더 유용하게 활용될 수 있게 해줍니다.
트레이트를 정의할 때, 메서드 시그니처에 필요한 매개변수를 포함할 수 있습니다:
trait Calculator {
fn add(&self, a: i32, b: i32) -> i32;
fn multiply(&self, a: i32, b: i32) -> i32;
}
이 Calculator 트레이트는 &self 외에도 각각 두 개의 정수를 인자로 받는 두 개의 메서드를 요구합니다. 이 트레이트를 구현하는 모든 타입은 이와 정확히 일치하는 시그니처를 가진 두 연산을 모두 제공해야 합니다.
구조체가 이를 구현하는 방법은 다음과 같습니다:
struct BasicCalc;
impl Calculator for BasicCalc {
fn add(&self, a: i32, b: i32) -> i32 {
a + b
}
fn multiply(&self, a: i32, b: i32) -> i32 {
a * b
}
}
이제 인수를 사용하여 이러한 메서드를 사용할 수 있습니다:
let calc = BasicCalc;
println!("{}", calc.add(5, 3)); // 8
println!("{}", calc.multiply(4, 7)); // 28
트레이트는 각 메서드가 어떤 매개변수를 받는지 정의하며, 구현은 해당 매개변수가 어떻게 사용되는지를 정의합니다. 이를 통해 서로 다른 타입들이 동일한 연산을 각자의 방식대로 수행할 수 있습니다. 예를 들어, LoggingCalc는 결과를 반환하기 전에 각 연산을 출력할 수도 있습니다.
챌린지
쉬움서로 다른 프로세서가 각자의 방식으로 텍스트를 변형할 수 있는 문자열 조작 툴킷을 만들어 봅시다! 매개변수를 받는 메서드들을 가진 TextProcessor 트레이트(trait)를 정의하고, 이를 두 가지 서로 다른 프로세서 타입에 대해 구현해 볼 것입니다.
코드는 다음 세 개의 파일로 구성됩니다:
processor.rs: 매개변수를 받는 두 개의 메서드를 가진 공개(public)TextProcessor트레이트를 정의합니다:repeat(&self, text: &str, times: u32) -> String— 주어진 텍스트를 지정된 횟수만큼 반복합니다.truncate(&self, text: &str, max_len: usize) -> String— 텍스트를 지정된 최대 길이로 자릅니다.
processors.rs: 트레이트를 구현하는 두 개의 공개 구조체(struct)를 생성합니다:SimpleProcessor— 반복 시 텍스트 사이에 공백을 넣고(예: "Hi"를 3번 반복하면 "Hi Hi Hi"가 됨), 자를 때는 단순히 최대 길이에서 텍스트를 끊는 유닛 구조체입니다.FancyProcessor— 반복 시 텍스트 사이에 " * "를 넣고(예: "Hi"를 3번 반복하면 "Hi * Hi * Hi"가 됨), 텍스트가 잘린 경우(원본 텍스트가 max_len보다 긴 경우에만) 끝에 "..."을 추가하는 유닛 구조체입니다.
main.rs: 모듈들을 하나로 모으고, 어떤 프로세서를 사용하느냐에 따라 동일한 트레이트 메서드가 어떻게 다른 결과를 생성하는지 보여줍니다.
메인 파일에서 두 프로세서를 모두 생성하고 입력값을 사용하여 테스트하세요. 세 가지 입력값(텍스트 문자열, 반복 횟수, 최대 길이)을 받게 됩니다.
각 프로세서의 동작을 보여주는 네 줄을 출력하세요:
Simple repeat: {result}
Simple truncate: {result}
Fancy repeat: {result}
Fancy truncate: {result}예를 들어, 입력값이 Hello, 3, 4인 경우:
Simple repeat: Hello Hello Hello
Simple truncate: Hell
Fancy repeat: Hello * Hello * Hello
Fancy truncate: Hell...두 프로세서가 모두 동일한 TextProcessor 규약을 따르지만, 각자 고유한 방식으로 텍스트를 변형하는 방식에 주목하세요. 트레이트는 메서드가 어떤 매개변수를 받는지를 정의하고, 각 구현체는 이를 어떻게 사용할지를 결정합니다!
세 가지 입력을 받게 됩니다: 처리할 텍스트, 반복 횟수(u32로 파싱), 그리고 자르기 위한 최대 길이(usize로 파싱).
치트 시트
트레이트(Trait) 메서드는 &self 외에도 추가적인 매개변수를 받을 수 있습니다:
trait Calculator {
fn add(&self, a: i32, b: i32) -> i32;
fn multiply(&self, a: i32, b: i32) -> i32;
}
매개변수가 있는 트레이트 구현하기:
struct BasicCalc;
impl Calculator for BasicCalc {
fn add(&self, a: i32, b: i32) -> i32 {
a + b
}
fn multiply(&self, a: i32, b: i32) -> i32 {
a * b
}
}
인수(arguments)와 함께 트레이트 메서드 사용하기:
let calc = BasicCalc;
println!("{}", calc.add(5, 3)); // 8
println!("{}", calc.multiply(4, 7)); // 28
트레이트는 각 메서드가 어떤 매개변수를 받는지 정의하고, 구현체는 해당 매개변수들이 어떻게 사용되는지를 정의합니다.
직접 해보기
mod processor;
mod processors;
use processor::TextProcessor;
use processors::{SimpleProcessor, FancyProcessor};
fn main() {
// 입력 읽기
let mut text = String::new();
std::io::stdin().read_line(&mut text).expect("Failed to read line");
let text = text.trim();
let mut times_input = String::new();
std::io::stdin().read_line(&mut times_input).expect("Failed to read line");
let times: u32 = times_input.trim().parse().expect("Failed to parse times");
let mut max_len_input = String::new();
std::io::stdin().read_line(&mut max_len_input).expect("Failed to read line");
let max_len: usize = max_len_input.trim().parse().expect("Failed to parse max_len");
// 프로세서 생성
let simple = SimpleProcessor;
let fancy = FancyProcessor;
// TODO: 프로세서를 사용하여 텍스트를 변환하고 결과를 출력하세요
// 네 줄을 출력하세요:
// Simple repeat: {result}
// Simple truncate: {result}
// Fancy repeat: {result}
// Fancy truncate: {result}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.