Created
June 18, 2013 17:37
-
-
Save javajosh/5807560 to your computer and use it in GitHub Desktop.
Doing groovy stuff
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Groovy has some nice features that make constructing new objects from maps. | |
//This file explores some of the ways we can get to collections, and nested collections of correctly typed objects. | |
class Player{ | |
String name | |
int seat | |
} | |
Player alice = [name: "alice", seat: 3] as Player | |
assert (alice instanceof Player) | |
//That's great. | |
// Now let's see if we can instantiate a list of players. | |
List<Player> players = [[name: "alice", seat: 3], [name: "bob", seat: 4]] as List<Player> | |
assert (players instanceof List<Player>) //this is true | |
assert !(players.first() instanceof Player) //this is false, alas :( | |
//Can we fix this type problem in code? | |
players = players.collect(new ArrayList<Player>()) {it as Player} | |
assert (players instanceof List<Player>) //this is true | |
assert (players.first() instanceof Player) //yay! | |
// Now we want to define a Game that has a bunch of players. How does that work? | |
class Game1{ | |
int id | |
List<Player> players | |
} | |
Game1 game1a = [id: 1, players:[[name: "alice", seat: 3], [name: "bob", seat: 4]]] as Game1 | |
assert (game1a instanceof Game1) | |
assert (game1a.players.first() instanceof LinkedHashMap) //boo | |
//So, we can construct the Game, but the players member is not of the correct type. How do we make it a list of players? | |
//Let's try using a nested 'as' Keyword. | |
Game1 game1b = [id: 1, players:[[name: "alice", seat: 3], [name: "bob", seat: 4]] as List<Player>] as Game1 | |
assert (game1b.players.first() instanceof LinkedHashMap) | |
//No, that had no effect. And for our use case it's not very helpful anyway even if it did work. | |
//Let's use our trick from above on the game.players member... | |
game1b.players = players.collect(new ArrayList<Player>()) {it as Player} | |
assert (game1b.players.first() instanceof Player) //sweet | |
//Unfortunately, we can't put that code in a constructor AND get the nice automatic property matching. So we resort to | |
//an init() method. | |
class Game2{ | |
int id | |
List<Player> players | |
void init(){ | |
players = players.collect(new ArrayList<Player>()) {it as Player} | |
} | |
} | |
Game2 game2 = [id: 1, players:[[name: "alice", seat: 3], [name: "bob", seat: 4]]] as Game2 | |
assert (game2 instanceof Game2) | |
game2.init() | |
assert (game2.players.first() instanceof Player) | |
//That's nice, except we have that annoying method call! Is there any way to avoid that? | |
//With this we'll use a Map constructor... | |
class Game3{ | |
int id | |
String name | |
List<Player> players | |
Game3(Map m){ | |
this.id = m.id | |
this.name = m.name | |
players = m.players.collect(new ArrayList<Player>()) {it as Player} | |
} | |
} | |
Game3 game3 = [id: 1, players:[[name: "alice", seat: 3], [name: "bob", seat: 4]]] as Game3 | |
assert (game3 instanceof Game3) | |
assert (game3.players.first() instanceof Player) | |
//Very cool! But we don't want to have to make constructors like that. Can we do better? | |
//The answer is "maybe" with some fancy meta programming involving accessing fields programmatically. | |
//But I think the better solution is to just bite the bullet and make a map constructor. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment