11.7. Using Closures Instead of ObjectsProblemYou want records with private state, behavior, and identity, but you don't want to learn object-oriented programming to accomplish this. SolutionWrite a function that returns (by reference) a hash of code references. These code references are all closures created in the same scope, so when they execute, they'll all share the same set of bindings to private variables. DiscussionBecause a closure is a binding of code and data, it can implement what might be thought of as an object.
Here's an example that creates and returns a hash of anonymous functions. $c1 = mkcounter(20); $c2 = mkcounter(77); printf "next c1: %d\n", $c1->{NEXT}->(); # 21 printf "next c2: %d\n", $c2->{NEXT}->(); # 78 printf "next c1: %d\n", $c1->{NEXT}->(); # 22 printf "last c1: %d\n", $c1->{PREV}->(); # 21 printf "old c2: %d\n", $c2->{RESET}->(); # 77
The code values in the hash references in sub mkcounter { my $count = shift; my $start = $count; my $bundle = { "NEXT" => sub { return ++$count }, "PREV" => sub { return --$count }, "GET" => sub { return $count }, "SET" => sub { $count = shift }, "BUMP" => sub { $count += shift }, "RESET" => sub { $count = $start }, }; $bundle->{"LAST"} = $bundle->{"PREV"}; return $bundle; }
Because the lexical variables used by the closures in the
The assignment right before the return makes both the The bundle we return is not an object in that it has no obvious inheritance and polymorphism. (Yet.) But it certainly does have state, behavior, and identity, as well as encapsulation. See AlsoThe section on "Closures" in Chapter 4 of Programming Perl and the discussion on closures in perlref (1); Recipe 11.4 ; Recipe 11.9 ; Chapter 13 |
|