পাঠ ৫.৩

Method Syntax

Method Syntax

Method function-এর মতোই — কিন্তু একটা struct, enum, বা trait object-এর সাথে যুক্ত। প্রথম parameter সবসময় self — যেই instance-এ method call করা হচ্ছে, সেটা।

impl block-এ method define

আগের area function-কে Rectangle-এর method-এ পরিণত করি:

src/main.rsrust
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
}

impl Rectangle block-এর ভিতরে যা থাকবে, সব Rectangle type-এর সাথে যুক্ত। Call করা হয় dot syntax-এ — rect1.area()

&self বনাম self বনাম &mut self

&self আসলে self: &Self-এর shorthand। Self impl block-এর type-এর alias।

  • &self — immutable borrow। শুধু read করা।
  • &mut self — mutable borrow। instance modify করা।
  • self (ownership) — rare। যখন method instance-কে অন্য কিছুতে transform করে, এবং পুরোনোটা আর use করতে চায় না।

আমরা শুধু read করছি, তাই &self

Field-এর নামে method

Method-এর নাম field-এর নামের সাথে মিলতে পারে। Rust parenthesis দিয়ে আলাদা করে — rect1.width() method, rect1.width field।

impl Rectangle {
    fn width(&self) -> bool {
        self.width > 0
    }
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    if rect1.width() {
        println!("The rectangle has a nonzero width; it is {}", rect1.width);
    }
}

শুধু field return-করা method-কে getter বলে। Rust auto-generate করে না, কিন্তু private field-কে controlled read access দিতে এই pattern useful।

Auto reference / dereference

C/C++-এ object-এর pointer থেকে method call করতে -> দরকার হয়। Rust-এ নেই — automatic reference/dereference। Method-এর signature দেখে Rust auto &, &mut, বা * insert করে।

#[derive(Debug,Copy,Clone)]
struct Point {
    x: f64,
    y: f64,
}

impl Point {
   fn distance(&self, other: &Point) -> f64 {
       let x_squared = f64::powi(other.x - self.x, 2);
       let y_squared = f64::powi(other.y - self.y, 2);

       f64::sqrt(x_squared + y_squared)
   }
}

let p1 = Point { x: 0.0, y: 0.0 };
let p2 = Point { x: 5.0, y: 6.5 };
p1.distance(&p2);
(&p1).distance(&p2);

দুটো call equivalent — Rust জানে method &self নিচ্ছে, তাই p1.distance(&p2)-এর p1-কে auto &p1 করে নেয়।

একাধিক parameter

src/main.rsrust
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 };
    let rect3 = Rectangle { width: 60, height: 45 };

    println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
    println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3));
}
terminal outputtext
Can rect1 hold rect2? true
Can rect1 hold rect3? false

self-এর পরে যত খুশি parameter — function-এর মতোই।

Associated function

impl block-এ যেসব function থাকে তাদের সবাই সেই type-এর associated functionself না নিলে এটা method না — instance ছাড়াও call করা যায়। Constructor pattern হিসেবে এটা common:

impl Rectangle {
    fn square(size: u32) -> Self {
        Self {
            width: size,
            height: size,
        }
    }
}

fn main() {
    let sq = Rectangle::square(3);
}

Self impl-এর type-এর alias — Rectangle-এর জায়গায় Self লেখা যায়। Call করা হয় Rectangle::square(3) — double colon। String::from, String::new এই pattern-এই।

একাধিক impl block

এক struct-এর একাধিক impl block দেওয়া যায় — নিচের code valid:

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

impl Rectangle {
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}

সাধারণত আলাদা করার দরকার নেই — কিন্তু generic type ও trait-এর context-এ (Chapter 10) এর অর্থ দাঁড়াবে।

এই পাঠ থেকে যা শিখলে

  • impl Type {...} block-এ method define; প্রথম parameter &self, &mut self, বা self
  • Method call dot syntax (obj.method()); Rust auto reference/dereference করে — -> লাগে না।
  • Method আর field-এর নাম একই হতে পারে — parenthesis দিয়ে আলাদা; getter pattern।
  • self-বিহীন function = associated function (constructor pattern); call Type::name()
  • Self = impl-এর type-এর alias। একাধিক impl block valid।