I have myself a nice, Dart modal dialog. It is an adapter for Element with the following constructors:
class ModalDialog implements Element { Element el, bg; factory ModalDialog() => new ModalDialog.tag('div'); ModalDialog.tag(String tag) { el = new Element.tag(tag); } ModalDialog.html(String html) { el = new Element.tag('div'); el.innerHTML = html; } // ... }The factory constructor allows me to instantiate a modal dialog thusly:
el = new ModalDialog(); el.innerHTML = '<form>...</form>';That works, but the factory constructor is more ceremony than Dart requires. In fact, I can use a redirecting constructor, as Kasper Lund pointed out. Thus I can still instantiate simple modal dialogs the same way if I change the constructor to:
class ModalDialog implements Element { Element el, bg; ModalDialog(): this.tag('div'); // ... }That is some compact syntax—the vanilla
ModalDialog()
constructor redirects to the ModalDialog.tag()
constructor with an argument of 'div'
. I really like that.Something else that Kasper mentioned was that redirection also works in constant constructors. Upon hearing that, I could only wonder what the heck is a constant constructor? To answer that, I return to my
Player
class:class Player { int x, y; Player.xy(this.x, this.y) { if (x == null) x = 0; if (y == null) y = 0; } }I can instantiate a player as
new Player.xy(25, 25);
and the player is positioned at x=25
and y=25
. The thing about most Dart classes is that you cannot simply assign them outside of functions:// this won't work... var me = new Player.xy(25, 25); main() { // do stuff here ... }The problem is that
new Player.xy(25, 25)
is not a compile time constant. I can declare the me
variable in a Dart libraries scope, but I cannot assign it—unless the assignment is a constant expression. Actual assignment is deferred until runtime (e.g. inside the main()
function).To convert
Player
into a compile time constant, I need to make all instance variables final:class Player { final int x, y; // ... }Admittedly, there is not much sense to a game in which all player positions are final, but why let that get in the way of a good topic exploration?
In addition to final instance variables, I also need a constant constructor. Here, I use a redirecting, constant constructor to point the vanilla
Player()
to the Player.xy()
version:class Player { final int x, y; const Player(): this.xy(0,0); Player.xy([this.x, this.y]) { if (x == null) x = 0; if (y == null) y = 0; } }With that, I can now instantiate a constant object at compile time:
final me = const Player(); main() { // Not much to do here since players don't move }Clearly I need a better use-case for constant objects that an immovable Player if I am to include a treatment of this topic in Dart for Hipsters. And I do need to include it—these redirecting constructors are quite nice.
Day #330
No comments:
Post a Comment