Nyx con Ejemplos

Cotas de Trait

Las cotas de trait (trait bounds) restringen parámetros de tipo genérico para que una función pueda llamar métodos de trait sobre valores de tipo desconocido. La sintaxis <T: TraitName> significa "esta función funciona para cualquier tipo T que implemente TraitName".

Código

// Trait bounds: función genérica que acepta cualquier tipo con Display

trait Display {
    fn to_string(self) -> String
}

struct Point {
    x: int,
    y: int
}

impl Display for Point {
    fn to_string(self) -> String {
        return "(" + int_to_string(self.x) + ", " + int_to_string(self.y) + ")"
    }
}

struct Circle {
    radius: int
}

impl Display for Circle {
    fn to_string(self) -> String {
        return "Circulo{radio=" + int_to_string(self.radius) + "}"
    }
}

fn print_it<T: Display>(x: T) -> String {
    return x.to_string()
}

fn show_twice<T: Display>(x: T) {
    let s: String = x.to_string()
    print(s)
    print(s)
}

fn main() -> int {
    let p: Point = Point { x: 7, y: 2 }
    print(print_it<Point>(p))

    let c: Circle = Circle { radius: 10 }
    print(print_it<Circle>(c))

    show_twice<Point>(p)

    return 0
}

Salida

(7, 2)
Circulo{radio=10}
(7, 2)
(7, 2)

Explicación

print_it<T: Display> es una función genérica que acepta cualquier tipo T siempre que implemente Display. La cota T: Display le indica al compilador dos cosas: que puede generar una versión especializada para cada tipo concreto usado en el sitio de la llamada (monomorfización), y que garantiza que x.to_string() siempre es una llamada válida dentro del cuerpo de la función.

show_twice demuestra que los genéricos con cota de trait son funciones ordinarias — pueden tener variables locales, llamar al método del trait varias veces y producir cualquier efecto secundario. El compilador produce versiones de código máquina separadas para Point y cualquier otro tipo que le pases, así que no hay sobrecarga de despacho virtual.

En el sitio de la llamada, el argumento de tipo se escribe explícitamente como print_it<Point>(p). Nyx a menudo puede inferir el argumento de tipo, pero ser explícito siempre es válido y a veces resulta más claro al leer el código.

← Anterior Siguiente →

Source: examples/by-example/22-trait-bounds.nx