💻 Exemplos: Capítulo 13: Traits, Generics e Polimorfismo Estático

Especialização em Sistemas com Rust • Demonstrações Práticas Compiláveis


🎯 Objetivo dos Exemplos

Demonstrar a criação de Traits (interfaces de comportamento), implementação para tipos customizados, funções genéricas parametrizadas com Trait Bounds (where T: Trait), polimorfismo em tempo de compilação (Monomorphization com custo zero de despacho dinâmico) e despacho dinâmico via Trait Objects (&dyn Trait).


1. Código Fonte Completo (src/main.rs)

//! Traits, Trait Bounds, Generics e Polimorfismo Estático vs Dinâmico

use std::fmt::Debug;

// 1. Definição de Trait com comportamento padrão opcional
pub trait DispositivoSerializavel {
    fn obter_identificador(&self) -> &str;
    fn serializar_para_wire(&self) -> Vec<u8>;

    // Método com implementação padrão (default method)
    fn exibir_sumario(&self) {
        println!("  Dispositivo ID: '{}' (Serialização pronta)", self.obter_identificador());
    }
}

// 2. Structs Concretas
#[derive(Debug, Clone)]
pub struct SensorTemperatura {
    pub id: String,
    pub temperatura_celsius: f32,
}

#[derive(Debug, Clone)]
pub struct AtuadorValvula {
    pub id: String,
    pub abertura_percentual: u8,
}

// 3. Implementações da Trait
impl DispositivoSerializavel for SensorTemperatura {
    fn obter_identificador(&self) -> &str {
        &self.id
    }

    fn serializar_para_wire(&self) -> Vec<u8> {
        let bytes_temp = self.temperatura_celsius.to_be_bytes();
        let mut buffer = Vec::new();
        buffer.extend_from_slice(b"TEMP:");
        buffer.extend_from_slice(&bytes_temp);
        buffer
    }
}

impl DispositivoSerializavel for AtuadorValvula {
    fn obter_identificador(&self) -> &str {
        &self.id
    }

    fn serializar_para_wire(&self) -> Vec<u8> {
        vec![b'V', b'A', b'L', b'V', self.abertura_percentual]
    }
}

// 4. Polimorfismo Estático (Static Dispatch via Monomorphization)
// O compilador gera cópias em código de máquina para cada tipo concreto T!
fn transmitir_estatico<T>(dispositivo: &T)
where
    T: DispositivoSerializavel + Debug,
{
    println!("\n[ESTÁTICO - Zero Cost] Transmitindo: {:?}", dispositivo);
    dispositivo.exibir_sumario();
    let bytes = dispositivo.serializar_para_wire();
    println!("Payload binário transmitido: {:?} ({} bytes)", bytes, bytes.len());
}

// 5. Polimorfismo Dinâmico (Dynamic Dispatch via Trait Objects: &dyn Trait)
// Permite coleções heterogêneas contendo diferentes tipos na mesma lista!
fn despachar_lote_dinamico(dispositivos: &[&dyn DispositivoSerializavel]) {
    println!("\n[DINÂMICO - Trait Object &dyn] Processando lote heterogêneo:");
    for disp in dispositivos {
        println!("Processando canal do dispositivo: '{}'", disp.obter_identificador());
        let payload = disp.serializar_para_wire();
        println!("  Bytes despachados: {:?}", payload);
    }
}

fn main() {
    println!("=== TRAITS, GENERICS E TRAIT BOUNDS ===");

    let sensor = SensorTemperatura {
        id: String::from("SENS_TEMP_ALPHA"),
        temperatura_celsius: 24.85,
    };

    let atuador = AtuadorValvula {
        id: String::from("VALV_GAS_BRAVO"),
        abertura_percentual: 75,
    };

    // 1. Invocando função genérica estática (monomorfizada)
    transmitir_estatico(&sensor);
    transmitir_estatico(&atuador);

    // 2. Criando coleção heterogênea com Trait Objects
    let lote_hardware: Vec<&dyn DispositivoSerializavel> = vec![&sensor, &atuador];
    despachar_lote_dinamico(&lote_hardware);
}

2. Saída Esperada no Terminal

=== TRAITS, GENERICS E TRAIT BOUNDS ===

[ESTÁTICO - Zero Cost] Transmitindo: SensorTemperatura { id: "SENS_TEMP_ALPHA", temperatura_celsius: 24.85 }
  Dispositivo ID: 'SENS_TEMP_ALPHA' (Serialização pronta)
Payload binário transmitido: [84, 69, 77, 80, 58, 65, 198, 204, 205] (9 bytes)

[ESTÁTICO - Zero Cost] Transmitindo: AtuadorValvula { id: "VALV_GAS_BRAVO", abertura_percentual: 75 }
  Dispositivo ID: 'VALV_GAS_BRAVO' (Serialização pronta)
Payload binário transmitido: [86, 65, 76, 86, 75] (5 bytes)

[DINÂMICO - Trait Object &dyn] Processando lote heterogêneo:
Processando canal do dispositivo: 'SENS_TEMP_ALPHA'
  Bytes despachados: [84, 69, 77, 80, 58, 65, 198, 204, 205]
Processando canal do dispositivo: 'VALV_GAS_BRAVO'
  Bytes despachados: [86, 65, 76, 86, 75]