Explain what's going on here in the following snippet.
enum WeatherStatus { initial, loading, success, failure }
extension WeatherStatusX on WeatherStatus {
bool get isInitial => this == WeatherStatus.initial;
bool get isLoading => this == WeatherStatus.loading;
bool get isSuccess => this == WeatherStatus.success;
bool get isFailure => this == WeatherStatus.failure;
}
CodePudding user response:
An extension
declaration associates members to a type.
Normally, in Dart, a method is either associated with a class or interface (instance methods) or with a static (class
/mixin
/library/etc) namespace (static methods).
An extension declaration instead associates methods directly with a type, which doesn't have to be an interface type (but can be).
When you try to call a method on something typed as WeatherStatus
, say
var status = WeatherStatus.initial;
print(status.isInitial);
the compiler first checks whether the WeatherStatus
interface has an isInitial
instance member.
Since it doesn't, it then goes on to check if there are any extension methods associated with the WeatherStatus
type.
There is (because the WeatherStatusX
extension is in scope), and then it instead calls WeatherStatusX(status).isInitial
which invokes that method with this
bound to the status object.
It's a way to add members on a type from the side, without needing to add them to the class itself (which you can't if it's not your class). The trade-off is that extension methods are not virtual. You can't add an override in a subclass, and get it called even if the caller only know the object at the superclass type, like you can for classes.
In reality, extension methods are most like static helper functions. You could write:
bool isInitial(WeatherStatus self) => self == WeatherStatus.initial;
and call it as isInitial(status)
. The extension declaration allows you to pretend that a static helper function is more like a special instance method, because you call it as status.isInitial
, but it really isn't an instance method. It just looks like one.
In this particular case, I'd recommend using the newest version of the Dart SDK so you can use the new enhanced enum
feature:
enum WeatherStatus {
initial, loading, success, failure;
bool get isInitial => this == initial;
bool get isLoading => this == loading;
bool get isSuccess => this == success;
bool get isFailure => this == failure;
}
This makes the isInitial
, etc., getters actual instance members on the enum
class. (Still can't override them, since enums can't have subclasses, but you don't need to worry about whether extension WeatherStatusX
is imported before you use them.)