Skip to main content

Command Palette

Search for a command to run...

Rust-এ Traits & Generics – In-depth

Published
5 min read
M

A self-motivated and enthusiastic web developer with a deep interest in JavaScript (React.js). To work in the Software industry with modern web technologies of different local & multinational Software/ IT agencies of Bangladesh and grow rapidly with increasing responsibilities.

Rust একটি memory safe এবং flexible language, যেখানে Traits এবং Generics code reuse এবং flexible behavior design করার জন্য খুব গুরুত্বপূর্ণ।


১️. Generics – Flexible Type

Generics হলো Rust-এর feature যা function, struct বা enum কে কোনো specific type এর উপর নির্ভর না করে তৈরি করতে দেয়।

উদাহরণ:

ধরো আমরা একটি online shop-এর জন্য function চাই যা সব ধরনের product price থেকে সবচেয়ে বড় price বের করবে।

fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
    largest
}

fn main() {
    let int_prices = vec![100, 250, 150];
    let float_prices = vec![99.5, 150.75, 120.0];

    println!("Most expensive (int): {}", largest(&int_prices));
    println!("Most expensive (float): {}", largest(&float_prices));
}

ব্যাখ্যা:

  • T → Generic type, function call-এর সময় decide হয়।

  • T: PartialOrd → type comparison করতে পারবে।

  • একই function দিয়ে different type (i32, f64) handle করা যায়।

Real-life meaning:

  • এক shop-এ বিভিন্ন ধরনের product price compare করতে পারছ।

  • Code reuse এবং type safety বজায় থাকে।


Struct + Generics Example:

struct Product<T> {
    name: String,
    price: T,
}

fn main() {
    let laptop = Product { name: "Laptop".to_string(), price: 1200 };
    let phone = Product { name: "Phone".to_string(), price: 699.99 };

    println!("{} costs {:?}", laptop.name, laptop.price);
    println!("{} costs {:?}", phone.name, phone.price);
}
  • এখানে Product<T> generic struct → price যে type-ই হোক, support করে।

  • একে type-safe এবং reusable রাখা হয়েছে।


২️. Traits – Shared Behavior

Traits হলো Rust-এর interface এর মতো। এটা বলে কোন type কি ধরনের behavior (methods) support করবে।

উদাহরণ: Pet Shop

ধরো একটি Pet Shop আছে। বিভিন্ন Pet আছে: Dog, Cat, Parrot। সব Pet speak করতে পারবে, কিন্তু শব্দ আলাদা।

trait Speak {
    fn speak(&self);
}

struct Dog;
struct Cat;
struct Parrot;

impl Speak for Dog {
    fn speak(&self) { println!("Woof!"); }
}

impl Speak for Cat {
    fn speak(&self) { println!("Meow!"); }
}

impl Speak for Parrot {
    fn speak(&self) { println!("Squawk!"); }
}

// Generic function with Trait Bound
fn make_pet_speak<T: Speak>(pet: T) {
    pet.speak();
}

fn main() {
    let pets: Vec<Box<dyn Speak>> = vec![
        Box::new(Dog),
        Box::new(Cat),
        Box::new(Parrot),
    ];

    for pet in pets {
        pet.speak();
    }
}

ব্যাখ্যা:

  • trait Speak → shared behavior define করে।

  • impl Speak for Dog/Cat/Parrot → প্রতিটি Pet নিজস্ব behavior define করে।

  • Box<dyn Speak> → runtime polymorphism, vector-এ সব Pet একসাথে রাখা যায়।

Real-life meaning:

  • Pet Shop-এর সব pet কে speak করতে বলা যায়, type যেটাই হোক না কেন।

  • Behavior flexible, code modular এবং clean।

Rust-এ dyn কি?

dyn হলো Rust-এর dynamic dispatch এর জন্য ব্যবহৃত keyword। এটি বলছে, “এই object যেকোনো type হতে পারে, যেটি এই trait implement করেছে।”

সংক্ষেপে:

  • Normally Rust compile-time dispatch ব্যবহার করে।

  • dyn Trait use করলে runtime dispatch হয়।

  • dyn allows heterogeneous types in a single variable বা collection।


১️ .Basic Example

ধরো আমাদের কাছে কিছু pet আছে, যেগুলো Speak trait implement করেছে:

trait Speak {
    fn speak(&self);
}

struct Dog;
struct Cat;

impl Speak for Dog {
    fn speak(&self) { println!("Woof!"); }
}

impl Speak for Cat {
    fn speak(&self) { println!("Meow!"); }
}

fn main() {
    let dog: Box<dyn Speak> = Box::new(Dog);
    let cat: Box<dyn Speak> = Box::new(Cat);

    dog.speak(); // Woof!
    cat.speak(); // Meow!
}

ব্যাখ্যা:

  • Box<dyn Speak> → heap-allocated pointer, runtime-এ actual type decide হয়।

  • Compile-time-এ Rust জানে না ঠিক কোন type হবে → dynamic dispatch

  • Method call speak() → function pointer table (vtable) ব্যবহার করে ঠিক কোন function call হবে runtime-এ।


2. কেন dyn দরকার?

Rust normally static dispatch use করে:

fn make_speak<T: Speak>(animal: T) {
    animal.speak();
}
  • T compile-time-এ resolve হয়।

  • Type fixed, memory stack-based, fast.

কিন্তু heterogeneous collection চাইলে:

let pets: Vec<Box<dyn Speak>> = vec![Box::new(Dog), Box::new(Cat)];
  • এখানে সব pet একসাথে রাখা দরকার।

  • Compile-time-এ type একই নয় → dyn ব্যবহার করতে হবে।


৩️. Memory & Dispatch Level

  1. Box<dyn Trait> memory:
[Pointer to heap data] + [Pointer to vtable]
  • Heap-allocated data → actual struct (Dog, Cat)

  • vtable pointer → function pointer table, যা বলে কোন method call হবে

  1. Dynamic dispatch:
  • pet.speak() call → vtable থেকে method pointer lookup → call actual function

  • Extra runtime cost থাকে (vtable lookup), কিন্তু type flexibility বেশি।


  • dyn vs Generic Trait Bound

FeatureSyntaxDispatchMemoryUse Case
GenericT: TraitCompile-timeStackType known at compile-time, fastest
Dynamicdyn TraitRuntimeHeap + vtableHeterogeneous types, collection of different types

Generics + Traits একসাথে

  • Generics দিয়ে আমরা function বা struct flexible করি।

  • Traits দিয়ে আমরা constraint দেই যে এই type কী behavior support করবে।

উদাহরণ:

trait Discount {
    fn discount(&self) -> f64;
}

struct Product {
    name: String,
    price: f64,
}

impl Discount for Product {
    fn discount(&self) -> f64 {
        self.price * 0.1 // 10% discount
    }
}

fn print_discount<T: Discount>(item: &T) {
    println!("Discount: {}", item.discount());
}

fn main() {
    let laptop = Product { name: "Laptop".to_string(), price: 1200.0 };
    print_discount(&laptop);
}

ব্যাখ্যা:

  • Discount trait → defines behavior

  • Product implements Discount → actual implementation

  • Generic function print_discount<T: Discount> → accepts any type যা Discount implement করে

Real-life meaning:

  • Shop-এ multiple product type থাকলেও একই way-তে discount calculate করা যায়।

  • Type-safe, flexible এবং reusable।

More from this blog

DSA মানে শুধু LeetCode না — DSA মানে Production System slow না করা

অনেকেই বলে — “ভাই, Web Development-এ DSA লাগে না” আসলে Junior Developer থাকলে এমনটাই মনে হয়।আমি নিজেও Junior থাকতে তাই ভাবতাম। আমার আবার একটা বাজে স্বভাব আছে 😅👉 কোন কিছুর বাস্তব প্রয়োজন না বুঝলে সেটা আমার মাথায় ঢুকে না। Junior থাকতে DSA শিখেছি...

Dec 24, 20253 min read
DSA মানে শুধু LeetCode না — DSA মানে Production System slow না করা

🦀 Rust-এ মেমরি ম্যানেজমেন্ট: GC ছাড়া In-depth.

Rust-এ Garbage Collector (GC) নেই, কিন্তু মেমরি নিরাপত্তা (memory safety) আর performance Rust-এর সবচেয়ে শক্তিশালী দিক।তাই, Go-এর মতো runtime-based GC না থাকা সত্ত্বেও Rust compile-time এ মেমরি ম্যানেজ করে Ownership System, Borrow Checker, আর Lifetime...

Oct 5, 202523 min read
🦀 Rust-এ মেমরি ম্যানেজমেন্ট: GC ছাড়া In-depth.

Morshedul Munna

45 posts

As a Software Developer, I am like an architect who designs and builds digital Products. I use my knowledge and expertise to create modern applications that are both efficient and elegant.

Rust-এ Traits & Generics – In-depth