Rust는 전통적인 객체지향 언어와는 다르지만, 객체지향 프로그래밍(OOP) 패러다임을 지원하는 여러 기능을 제공합니다. Rust에서 객체지향 프로그래밍을 구현하는 주요 방법에는 구조체, 트레잇, 그리고 트레잇 객체가 있습니다.
구조체는 객체의 상태를 나타내는 필드를 정의합니다. impl 블록을 사용하여 구조체에 메서드를 정의할 수 있습니다.
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
}
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
let rect2 = Rectangle {
width: 10,
height: 40,
};
println!("The area of the rectangle is {} square pixels.", rect1.area());
println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
}
위 예제에서 Rectangle 구조체는 width와 height 필드를 가집니다. impl 블록을 사용하여 area와 can_hold 메서드를 정의합니다. area 메서드는 사각형의 면적을 계산하고, can_hold 메서드는 다른 사각형을 포함할 수 있는지 확인합니다.
트레잇은 객체의 동작을 정의하는 인터페이스입니다. 트레잇을 사용하여 구조체에 공통된 동작을 구현할 수 있습니다.
trait Shape {
fn area(&self) -> f64;
}
struct Circle {
radius: f64,
}
impl Shape for Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * self.radius * self.radius
}
}
struct Square {
side: f64,
}
impl Shape for Square {
fn area(&self) -> f64 {
self.side * self.side
}
}
fn main() {
let circle = Circle { radius: 5.0 };
let square = Square { side: 3.0 };
println!("The area of the circle is {} square units.", circle.area());
println!("The area of the square is {} square units.", square.area());
}
위 예제에서 Shape 트레잇은 area 메서드를 정의합니다. Circle과 Square 구조체는 Shape 트레잇을 구현하여 각각의 면적을 계산합니다.
트레잇 객체는 런타임에 동적 디스패치를 사용하여 다양한 타입의 객체를 처리할 수 있게 합니다. Box<dyn Trait>를 사용하여 트레잇 객체를 생성할 수 있습니다.
trait Shape {
fn area(&self) -> f64;
}
struct Circle {
radius: f64,
}
impl Shape for Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * self.radius * self.radius
}
}
struct Square {
side: f64,
}
impl Shape for Square {
fn area(&self) -> f64 {
self.side * self.side
}
}
fn print_area(shape: &dyn Shape) {
println!("The area is {} square units.", shape.area());
}
fn main() {
let circle = Circle { radius: 5.0 };
let square = Square { side: 3.0 };
print_area(&circle);
print_area(&square);
}
위 예제에서 print_area 함수는 Shape 트레잇 객체를 인자로 받아서 면적을 출력합니다. &dyn Shape는 다양한 타입의 Shape 구현체를 처리할 수 있게 합니다.
Rust는 객체지향 프로그래밍의 주요 개념을 지원하면서도, 소유권 시스템과 타입 시스템을 통해 메모리 안전성과 성능을 보장합니다.
객체지향 특성
캡슐화: 구조체와 impl 블록을 사용한 데이터 은닉
예제: 은행 계좌 시스템 구현
pub struct BankAccount {
balance: f64,
account_holder: String
}
impl BankAccount {
pub fn deposit(&mut self, amount: f64) { ... }
pub fn withdraw(&mut self, amount: f64) -> Result<f64, String> { ... }
}
상속과 트레잇: 코드 재사용과 다형성
예제: 도형 계층 구조 구현
trait Shape {
fn area(&self) -> f64;
fn perimeter(&self) -> f64;
}
struct Circle { radius: f64 }
struct Rectangle { width: f64, height: f64 }
트레잇 객체
동적 디스패치 구현
예제: 게임 캐릭터 시스템
trait Character {
fn attack(&self);
fn defend(&self);
}
struct Player { ... }
struct Enemy { ... }
let game_objects: Vec<Box<dyn Character>> = vec![
Box::new(Player {...}),
Box::new(Enemy {...})
];
상태 패턴
러스트에서 열거형을 활용한 상태 관리
예제: 주문 처리 시스템
enum OrderState {
Created { id: u32 },
Confirmed { payment_id: String },
Shipped { tracking_number: String },
Delivered { delivery_date: DateTime },
}
struct Order {
state: OrderState,
items: Vec<Item>,
}