Middle
Onde utilizou genéricos na sua experiência de desenvolvimento?
sobes.tech IA
Resposta da IA
Utilizou genéricos:
- Para implementar coleções seguras em termos de tipos. Por exemplo,
ArrayList<MyObject>em vez deArrayListbruto, o que previne erros em tempo de execução relacionados com a conversão de tipos.// Abordagem não segura em termos de tipos (tipo bruto) List list = new ArrayList(); list.add("String"); list.add(123); // Adiciona um int // Abordagem segura com genéricos List<String> stringList = new ArrayList<>(); stringList.add("String"); // stringList.add(123); // O compilador irá gerar erro - Para criar adaptadores universais para RecyclerView. Permite reutilizar a lógica do adaptador para diferentes tipos de dados.
// Exemplo de ViewHolder universal class GenericViewHolder<T>(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind(item: T) { // Lógica de ligação de dados dependendo do tipo T } } // Exemplo de adaptador universal class GenericAdapter<T>(private val items: List<T>) : RecyclerView.Adapter<GenericViewHolder<T>>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GenericViewHolder<T> { // Criação do ViewHolder } override fun onBindViewHolder(holder: GenericViewHolder<T>, position: Int) { holder.bind(items[position]) } override fun getItemCount() = items.size } - Para a criação de fábricas de objetos. Para obter um tipo específico de objeto sem conversão explícita.
interface Factory<T> { T create(); } class StringFactory implements Factory<String> { @Override public String create() { return "Nova string"; } } class IntegerFactory implements Factory<Integer> { @Override public Integer create() { return 100; } } Factory<String> stringFactory = new StringFactory(); String myString = stringFactory.create(); // Obtem um String sem conversão - Para restringir tipos em métodos e classes. Uso de genéricos restritos (
<T extends MyInterface>ou<T super MyClass>) para garantir que o tipo genérico implemente uma interface específica ou herde de uma classe.// Método que aceita uma lista de elementos que implementam Serializable public <T extends Serializable> void saveObjectList(List<T> list) { // Lógica de salvamento } - Em componentes arquiteturais. Por exemplo, ao trabalhar com LiveData ou ViewModel, os genéricos são frequentemente usados para definir o tipo de dados que eles gerenciam.
// LiveData para uma lista de objetos de um tipo definido val myData: LiveData<List<MyItem>> = // inicialização // ViewModel com dados de um tipo definido class MyViewModel : ViewModel() { val data: MutableLiveData<MyStateType> by lazy { MutableLiveData<MyStateType>() } } - No desenvolvimento de clientes de rede. Para a desserialização automática de respostas do servidor em objetos de um tipo específico.
// Exemplo de serviço Retrofit com genérico na resposta interface ApiService { @GET("users") Call<List<User>> getUsers(); @GET("products/{id}") Call<Product> getProduct(@Path("id") String productId); }
Genéricos melhoraram significativamente a segurança de tipos, legibilidade e reutilização de código.