Sobes.tech
Middle

Къде сте използвали генерични типове в опита си за разработка?

sobes.tech AI

Отговор от AI

Общи използвани генерични:

  • За реализиране на типобезопасни колекции. Например, ArrayList<MyObject> вместо суров ArrayList, което предотвратява грешки по време на изпълнение, свързани с преобразуване на типове.
    // Нестандартиран подход (суров тип)
    List list = new ArrayList();
    list.add("Ред");
    list.add(123); // Добавяне на int
    
    // Типобезопасен подход с генерични типове
    List<String> stringList = new ArrayList<>();
    stringList.add("Ред");
    // stringList.add(123); // Компилаторът ще даде грешка
    
    
  • За създаване на универсални адаптери за RecyclerView. Позволява повторно използване на логиката на адаптера за различни типове данни.
    // Пример за универсален ViewHolder
    class GenericViewHolder<T>(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(item: T) {
            // Логика за свързване на данни в зависимост от типа T
        }
    }
    
    // Пример за универсален адаптер
    class GenericAdapter<T>(private val items: List<T>) : RecyclerView.Adapter<GenericViewHolder<T>>() {
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GenericViewHolder<T> {
            // Създаване на ViewHolder
        }
    
        override fun onBindViewHolder(holder: GenericViewHolder<T>, position: Int) {
            holder.bind(items[position])
        }
    
        override fun getItemCount() = items.size
    }
    
  • За създаване на фабрики за обекти. За получаване на конкретен тип обект без явна конверсия.
    interface Factory<T> {
        T create();
    }
    
    class StringFactory : Factory<String> {
        override fun create(): String {
            return "Нова редица";
        }
    }
    
    class IntegerFactory : Factory<Int> {
        override fun create(): Int {
            return 100;
        }
    }
    
    Factory<String> stringFactory = StringFactory();
    val myString: String = stringFactory.create(); // Получаване на String без преобразуване
    
  • За ограничаване на типове в методи и класове. Използване на ограничени генерични типове (<T extends MyInterface> или <T super MyClass>) за гарантиране, че типът генерик реализира определен интерфейс или наследява от определен клас.
    // Метод, който приема списък от елементи, реализиращи интерфейса Serializable
    public <T extends Serializable> void saveObjectList(List<T> list) {
        // Логика за запазване
    }
    
  • В архитектурните компоненти. Например, при работа с LiveData или ViewModel, често се използват генерични типове за определяне на типа данни, които управляват.
    // LiveData за списък от обекти от определен тип
    val myData: LiveData<List<MyItem>> = // инициализация
    
    // ViewModel с данни от определен тип
    class MyViewModel : ViewModel() {
        val data: MutableLiveData<MyStateType> by lazy {
            MutableLiveData<MyStateType>()
        }
    }
    
  • При разработка на мрежови клиенти. За автоматично десериализиране на отговорите от сървъра към конкретни типове обекти.
    // Пример за Retrofit услуга с генерик в отговора
    interface ApiService {
        @GET("users")
        Call<List<User>> getUsers();
    
        @GET("products/{id}")
        Call<Product> getProduct(@Path("id") String productId);
    }
    

Генериците значително повишиха типобезопасността, четливостта и възможността за повторно използване на кода.