The most important method in SpellAbility is resolve(), which does the "action" of the card like dealing 2 damage or destroying all creatures but I haven't talked about what really goes into resolve(). The idea behind resolve() is the Command Pattern, "I don't care how you do it, just do it."
So resolve() can have anything in it, but of course the rest of the program has to support it. I have tried programming Time Walk (1U, Take an extra turn after this one), but MTG Forge's phases are messed up and yes they are messed up because me (darn those phases). Odd fact, the pre-alpha Time Walk said "Opponent loses next turn", you can read more here. It was changed because a player thought that his opponent immediately lost game, instead of just losing a turn.
The resolve() of most cards does something like destroying a creature or dealing damage. Many of these actions are done using the GameAction object which handles actions involving a game of Magic like newGame(). (GameAction isn't a great name, but you have to name it something.)
GameAction.destroy(Card c) can destroy any card in play. The Card object itself is dealt damage, Card.addDamage(int n), addDamage() is more correct than "setDamage(int n)" because you are "adding more damage to the card." You must use addDamage() since the card may have other damage.
In retrospect, it probably would have been better to put addDamage() in GameAction in order to let GameAction check for other effects that might trigger when damage is dealt. Some abilities only trigger during combat so GameAction would also need addCombatDamage(int n) as well because combat damage is different than regular damage.
"Opening up a working system is more like opening up a human brain and replacing a nerve than opening up a sink and replacing a washer. Would maintenance be easier if it was called Software Brain Surgery?"