AnyCompiler

Traits

Ek trait un methods ka set define karta hai jo ek type implement kar sakta hai — doosri languages mein interface jaisa. Ek baar jab koi type ek trait implement kar deta hai, aap us trait ke methods ko directly usper call kar sakte ho.

trait Greet {
    fn greet(&self) -> String;
}

struct Person {
    name: String,
}

impl Greet for Person {
    fn greet(&self) -> String {
        format!("Hello, my name is {}", self.name)
    }
}

fn main() {
    let alice = Person { name: String::from("Alice") };
    println!("{}", alice.greet());
}
Output
Hello, my name is Alice

Trait bounds

Ek generic function require kar sakta hai ki uska type parameter ek particular trait implement kare, jo T: Greet se likha jaata hai. Yeh greet_everyone ko kisi bhi aise type ka slice accept karne deta hai jo Greet implement karta ho, sirf specifically Person nahi — function ek baar likha jaata hai aur har us type ke liye kaam karta hai jo bound ko satisfy karta hai.

trait Greet {
    fn greet(&self) -> String;
}

struct Person {
    name: String,
}

impl Greet for Person {
    fn greet(&self) -> String {
        format!("Hello, my name is {}", self.name)
    }
}

fn greet_everyone<T: Greet>(items: &[T]) {
    for item in items {
        println!("{}", item.greet());
    }
}

fn main() {
    let people = vec![
        Person { name: String::from("Alice") },
        Person { name: String::from("Bob") },
    ];
    greet_everyone(&people);
}
Output
Hello, my name is Alice
Hello, my name is Bob

Aage: generics — ek aisa function ya struct likhna jo kai types ke across kaam kare, woh general mechanism jispar trait bounds bante hain.

Practice Exercise

Ek trait Area define karo jiska method area(&self) -> f64 ho. Ise ek struct Square { side: f64 } ke liye implement karo taaki area(), side * side return kare. side 4.0 wala ek Square banao aur uska area() print karo.