Rust de los fundamentos al dominio — Lección 5
Cree API reutilizables con genéricos, características y vidas útiles
Los artículos escritos en este blog fueron creados con el objetivo de enseñar. Además, la información del artículo puede ser incorrecta, así que tenga cuidado.
Los genéricos reutilizan las mismas reglas sólo para diferentes tipos, y los rasgos definen el comportamiento que un tipo debe proporcionar. Las notaciones de duración describen al compilador las relaciones entre referencias.
Definir comportamiento con rasgos
trait Damageable {
fn is_alive(&self) -> bool;
fn take_damage(&mut self, amount: i32);
}
fn attack(target: &mut impl Damageable, damage: i32) {
if target.is_alive() {
target.take_damage(damage);
}
}
El ataque puede utilizar un valor que implemente Damageble sin conocer el tipo concreto. Un rasgo está más cerca de un contrato de comportamiento requerido que de una jerarquía de herencia.
Genéricos y rasgos vinculados
fn strongest<T>(values: &[T]) -> Option<&T>
where
T: Ord,
{
values.iter().max()
}
Dado que existe la condición de que T implemente Ord, el compilador sabe que los valores se pueden comparar. Las combinaciones de tipos no válidas se rechazan antes de la ejecución.
implementación de rasgos
struct Monster {
health: i32,
}
impl Damageable for Monster {
fn is_alive(&self) -> bool {
self.health > 0
}
fn take_damage(&mut self, amount: i32) {
self.health = (self.health - amount).max(0);
}
}
Al separar los datos y los contratos comunes, los rasgos se pueden implementar en la medida que lo permitan los tipos externos.
relación de vida
fn longer<'a>(a: &'a str, b: &'a str) -> &'a str {
if a.len() >= b.len() { a } else { b }
}
'a representa la relación en la que la referencia de retorno no puede sobrevivir a las dos referencias de entrada. No es una función para extender la vida útil real de una referencia o crear un recurso de tiempo de ejecución.
El compilador infiere la vida útil más simple. En lugar de aumentar la notación cuando ocurre un error, primero debe verificar la relación de propiedad de la API para ver qué entrada toma prestada el valor de retorno.