I hope you’ve already checked the Abstract & Generic . We already know what abstract class is and it can be extend from anywhere by importing the abstract class. It offered the benefits of restriction extending class outside the library.
abstract class ApiState {}
class Loading extends ApiState {}
class Success extends ApiState {}
class Error extends ApiState {}
But we create a sealed class, it can not be only extend from that library/file.
Note each file is a library, and you can use
part/part ofto combine multiple file.
using sealed
sealed class ApiState {}
class Loading extends ApiState {}
class Success extends ApiState {}
class Error extends ApiState {}
And if we you try to extend ApiState outside the file,
It will give you error.
Also other things to keep in mind
- Sealed class can not be instantiated.
- Subclasses can be normal, abstract, final, or sealed.
Which means, even though we can not extend
ApiStateBut we can extend subclass and any other things we can do with normal class; Theses are just normal class.
How is it different from creating enum then?
We can have fields and other every stuff that a class offer in enum. But all the enum Fields, will be verbose, And Unnecessary optional fields.
enum ApiState {
loading,
success,
error;
final String? data;
final String? message;
final int? status;
}
Every state has these fields, but most of them don’t apply to most states.
But enums are useful
When we only care which value it is, and all possible values share the same structure.
- Enum: Which value is it?
- Sealed class: Which type is it, and what data does it carry?
benefits of using sealed class
sealed class ApiState {
const ApiState();
}
class Loading extends ApiState {}
class Success extends ApiState {
const Success(this.data);
final String data;
}
class Error extends ApiState {
const Error(this.status, this.message);
final String message;
final int status;
}
destructuring/pattern matching
final Error err = Error(400, "err");
final Error(:message) = Error(400, "err");
print(message);
We must use the same field name (
:message) for this.
void main() {
final states = [Loading(), Success("ok"), Error(400, "err")];
for (final state in states)
switch (state) {
case Loading():
print("loading");
case Success(:final data):
print(data);
case Error(:final status):
print(status);
}
}