问题
I have an abstract class Event
and a concrete subclass that extends it called PlaceChangeEvent
. Inside an event listener, I have the following code:
void onEvent(Event event) {
PlaceChangeEvent pce = null;
if(event is PlaceChangeEvent)
pce = (PlaceChangeEvent)event; // <== error is here
else
throw new Exception("Event is not a PlaceChangeEvent.");
Place place = pce.place;
presenterProvider.display(place);
}
So if the runtime type of event
is PlaceChangeEvent
, then I need to cast the event to that type so that I can access its properties. But I'm getting a compiler error on the typecast, stating:
A value of type 'Type' cannot be assigned to a variable of type 'PlaceChangeEvent'
Where am I going wrong, and what do I need to do to fix it?
回答1:
In Dart
upcasts are implicit. If
B
is a subclass ofA
, thenB b = a
(wherea
is an instance of classA
) is warning free and silently castsa
toB
. In Java you would have needed to writeB b = (B) a
.the dynamic type is an always-present escape hatch. If
B
andC
are not in the same hierarchy, then temporarily assigning to the dynamic type will make the cast warning-free.B b = someB; var tmp = b; C c = tmp;
One can do an explicit check using
is
. Theis
check returns true if the object is of the right type. There are also some very simple rules that propagate is-check types. For example, ifis
is used inside anif
condition, then the corresponding branch uses this information for type-warnings.Object o; o.foo(); // warning: foo does not exist on Object. if (o is A) { // assuming that A contains 'foo'. o.foo(); // warning-free. }
One can explicitly check and throw if a type is not the expected one with
as
. This operator does not throw when the left-hand side isnull
.
For your example this boils down to:
No explicit check (1):
void onEvent(Event event) {
// Implicit upcast. PlaceChangeEvent is subclass of Event.
PlaceChangeEvent pce = event;
Place place = pce.place;
presenterProvider.display(place);
}
With an is-check (3):
void onEvent(Event event) {
if (event is PlaceChangeEvent) {
// Static type system propagates type. No need for variable.
Place place = event.place;
presenterProvider.display(place);
} else {
// Note: this doesn't look like an exception, but an error.
throw new Exception("Event is not a PlaceChangeEvent.");
}
}
Using as
(4):
void onEvent(Event event) {
Place place = (event as PlaceChangeEvent).place;
presenterProvider.display(place);
}
Alternatively, if you expect to receive a PlaceChangeEvent, you should simply change the type of the argument:
void onEvent(PlaceChangeEvent event) {
Place place = event.place;
presenterProvider.display(place);
}
In checked mode this will catch bad types, and in unchecked mode it will throw when accessing event.place
. This is generally the preferred way.
回答2:
Try this:
pce = event as PlaceChangeEvent;
来源:https://stackoverflow.com/questions/20859702/dart-typecasting-error