0

I'm trying to implement a BLOC pattern for the Flutter project, my code is plentifully reusable, so I decide to use generic programming to implement it.

First I defined the event classes:

import 'package:flutter_bloc/flutter_bloc.dart';

abstract class AbstractSelectionEvent<T> {
  final T obj;

  AbstractSelectionEvent(this.obj);
}

class SelectedEvent<T> extends AbstractSelectionEvent<T> {
  SelectedEvent(T obj) : super(obj);
}

class UnselectedEvent<T> extends AbstractSelectionEvent<T> {
  UnselectedEvent(T obj) : super(obj);
}

class ChangeSelectionEvent<T> extends AbstractSelectionEvent<T> {
  ChangeSelectionEvent(T obj) : super(obj);
}

Then the state classes:

abstract class AbstractSelectionState<T> {
  final Set<T> selected;

  AbstractSelectionState(this.selected);

  AbstractSelectionState<T> select(T obj);

  AbstractSelectionState<T> unselect(T obj);

  AbstractSelectionState<T> changeSelect(T obj);

  AbstractSelectionState<T> reset(T obj);
}

class SelectedState<T> extends AbstractSelectionState<T> {
  SelectedState(Set<T> selected) : super(selected);

  SelectedState<T> select(T obj) => SelectedState<T>(selected..add(obj));

  SelectedState<T> unselect(T obj) => SelectedState<T>(selected..remove(obj));

  SelectedState<T> changeSelect(T obj) =>
      selected.contains(obj) ? unselect(obj) : select(obj);

  SelectedState<T> reset(T obj) => SelectedState<T>(<T>{});
}

Finally, When I wrote the BLOC class I face some troubles.


abstract class SelectionBloc<
    T,
    E extends AbstractSelectionEvent<T>,
    S extends AbstractSelectionState<T>
  > extends Bloc<E, S> {
  SelectionBloc(S initialState) : super(initialState) {
    
    // ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ The first error
    on<SelectedEvent<T>>((event, emit) {
      
      //   ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ The second error
      emit(state.select(event.obj));
      
    });
    
  }
}

The first error says

'SelectedEvent<T>' doesn't conform to the bound 'E' of the type parameter 'E'.


Try using a type that is or is a subclass of 'E'.

The second error:

The argument type 'AbstractSelectionState<T>' can't be assigned to the parameter type 'S'.

For the second error, I know that select, unselect, changeSelect, reset functions return AbstractSelectionState<T>.

And SelectionBloc expects S state for emit function, which is subclass of AbstractSelectionState<T>.

But from another side, the AbstractSelectionState<T> class is abstract, which means that the returned value of the functions must be an instance of AbstractSelectionState<T> subclasses.

Is this issue can be fixed?

nvoigt
  • 75,013
  • 26
  • 93
  • 142
Ayad Salim
  • 88
  • 7

1 Answers1

0

This should work:

abstract class SelectionBloc<T>
    extends Bloc<AbstractSelectionEvent<T>, AbstractSelectionState<T>> {

  SelectionBloc(AbstractSelectionState<T> initialState) : super(initialState) {
    
    on<AbstractSelectionEvent<T>>((
      event,
      emit,
    ) {
      emit(state.select(event.obj));
    });
    
  }
}
Er1
  • 2,559
  • 1
  • 12
  • 24