Pular para conteúdo

Aula 10 - Generics e Traits 🧬

Objetivo

Objetivo: Dominar o uso de Tipos Genéricos para criar código reutilizável e entender como as Traits (Traços) definem comportamentos compartilhados entre diferentes tipos.


1. Tipos Genéricos (Generics) 🧩

Generics permitem que as funções e estruturas trabalhem com múltiplos tipos sem duplicar código.

Em Funções

fn maior<T: PartialOrd>(lista: &[T]) -> &T {
    let mut maior = &lista[0];
    for item in lista {
        if item > maior {
            maior = item;
        }
    }
    maior
}

Em Structs

struct Ponto<T> {
    x: T,
    y: T,
}

let p1 = Ponto { x: 5, y: 10 };       // Ponto de i32
let p2 = Ponto { x: 1.0, y: 4.0 };   // Ponto de f64

2. Traits: Definindo Comportamento 🛠️

Uma Trait diz ao compilador sobre a funcionalidade que um tipo específico possui e pode compartilhar com outros tipos. É similar a uma Interface em outras linguagens.

pub trait Resumo {
    fn resumir(&self) -> String;
}

pub struct Artigo {
    pub titulo: String,
    pub autor: String,
}

impl Resumo for Artigo {
    fn resumir(&self) -> String {
        format!("{}: {}", self.titulo, self.autor)
    }
}

3. Trait Bounds: Restringindo Generics ⛓️

Podemos usar Trait Bounds para especificar que um tipo genérico deve implementar uma determinada Trait.

pub fn notificar<T: Resumo>(item: &T) {
    println!("Notícia! {}", item.resumir());
}

4. Visualização: Polimorfismo com Traits 🎭

classDiagram
    class Resumo {
        <<interface>>
        +resumir() String
    }
    class Artigo {
        +titulo String
        +resumir() String
    }
    class Tweet {
        +username String
        +resumir() String
    }
    Resumo <|.. Artigo
    Resumo <|.. Tweet

5. Mini-Projeto: Sistema de Notificações 🔔

Desenvolva uma estrutura para um sistema de comunicação: 1. Defina uma Trait Notificavel com o método enviar(&self). 2. Crie Structs Email, SMS e WhatsApp. 3. Implemente a Trait Notificavel para cada uma delas (ex: o e-mail imprime "Enviando e-mail para...", etc). 4. Crie uma função genérica que receba uma lista de objetos que implementam Notificavel e chame o método enviar para todos.


6. Exercício de Fixação 🧠

  1. Qual a vantagem de usar Generics em vez de duplicar funções para cada tipo?
  2. O que acontece se chamarmos a função maior em um tipo que não implementa a comparação (PartialOrd)?
  3. Podemos implementar uma Trait em um tipo que não criamos? (Ex: impl MinhaTrait for i32). Justifique.

Próxima Aula: Vamos explorar o lado funcional do Rust com Programação Funcional: Closures e Iterators! 🚀