CodeBlanks Logo Icon CodeBlanks

Supertrait

Constrain a trait with another trait using a supertrait.

Supertraits

A trait can depend on another trait: trait A: B means "every type implementing A must also implement B". A's default methods can use B's methods:

use std::fmt::Display;

trait Raporlanir: Display {
    fn rapor(&self) -> String {
        format!("[rapor] {self}")      // thanks to Display
    }
}

struct Sicaklik(f64);
impl Display for Sicaklik {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}°C", self.0)
    }
}
impl Raporlanir for Sicaklik {}

This isn't inheritance: the supertrait's implementation is written separately; only its existence is required.

Why is it useful?

Supertraits gather the abilities a trait needs in one place. For example std::error::Error: Debug + Display; every error type is automatically printable. Eq: PartialEq, Ord: Eq + PartialOrd and Copy: Clone are other examples in the standard library.

fn hepsini_raporla(v: &[&dyn Raporlanir]) {
    for x in v {
        println!("{}", x.rapor());   // Display is reachable too
    }
}

Practice Reportable temperature

Write the Raporlanir trait above and the Sicaklik type (Display: {}°C). Print the result of Sicaklik(21.5).rapor().

Starter code

main.rs
use std::fmt::{self, Display};

fn main() {
    // buraya yaz
}

Sample solution

main.rs
use std::fmt::{self, Display};

trait Raporlanir: Display {
    fn rapor(&self) -> String {
        format!("[rapor] {self}")
    }
}

struct Sicaklik(f64);

impl Display for Sicaklik {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}°C", self.0)
    }
}

impl Raporlanir for Sicaklik {}

fn main() {
    println!("{}", Sicaklik(21.5).rapor());
}

Expected output

[rapor] 21.5°C

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What happens if <code>impl Raporlanir for X {}</code> is written for a type not implementing Display?

  • E0277: X doesn't implement Display Correct answer
  • Display is generated automatically
  • It works
  • A warning

Explanation: The supertrait bound is a precondition of the subtrait implementation.

2 Supertrait

Question
trait Raporlanir____ {
    fn rapor(&self) -> String {
        format!("[rapor] {self}")
    }
}
Answer
trait Raporlanir: Display {
    fn rapor(&self) -> String {
        format!("[rapor] {self}")
    }
}

Explanation: trait A: B requires implementers of A to implement B too.

3 Trait and its supertrait

Term Meaning
Error Debug + Display
Eq PartialEq
Copy Clone
Ord Eq + PartialOrd

All lessons in Advanced