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); }
Генериците значително повишиха типобезопасността, четливостта и възможността за повторно използване на кода.