個人的にクロージャが使えればクラスの構文は要らないと思っている。例としてスタックを表すクラスをクロージャを使って定義してみる。
まず、D言語で。
import std.array; template Stack(T) { // Stackクラスに相当 struct Stack { void delegate(T) push; // 構造体メンバはpublicになる。 T delegate() pop; // 構造体メンバはpublicになる。 } // Stack.new()に相当 Stack create() { Stack obj; // Stackオブジェクトに相当 T[] arr = []; // レキシカル変数のためprivateになる。 // メソッドの定義(クロージャ) obj.push = (T n) { arr ~= n; }; obj.pop = () { auto b = arr.back; arr.popBack; return b; }; return obj; } } import std.stdio; void main() { auto a = Stack!(int).create(); auto b = Stack!(int).create(); a.push(0); b.push(5); a.push(1); b.push(6); a.push(2); b.push(7); a.push(3); b.push(8); a.push(4); b.push(9); writeln( "a:", a.pop(), " b:", b.pop() ); // a:4 b:9 writeln( "a:", a.pop(), " b:", b.pop() ); // a:3 b:8 writeln( "a:", a.pop(), " b:", b.pop() ); // a:2 b:7 writeln( "a:", a.pop(), " b:", b.pop() ); // a:1 b:6 writeln( "a:", a.pop(), " b:", b.pop() ); // a:0 b:5 }
そして、Perlでも。
#! /usr/bin/perl use strict; use warnings; # Stack::new()に相当 sub Stack_create { my %Stack; # Stackオブジェクトに相当 my @arr = (); # レキシカル変数のためprivateになる。 # メソッドの定義(クロージャ) $Stack{"push"} = sub { # ハッシュメンバはpublicになる。 my ($n) = @_; push @arr, $n; }; $Stack{"pop"} = sub { # ハッシュメンバはpublicになる。 return pop @arr; }; return \%Stack; } my $a = Stack_create(); my $b = Stack_create(); $a->{"push"}->(0); $b->{"push"}->(5); $a->{"push"}->(1); $b->{"push"}->(6); $a->{"push"}->(2); $b->{"push"}->(7); $a->{"push"}->(3); $b->{"push"}->(8); $a->{"push"}->(4); $b->{"push"}->(9); print "a:", $a->{"pop"}->(), " b:", $b->{"pop"}->(), "\n"; # a:4 b:9 print "a:", $a->{"pop"}->(), " b:", $b->{"pop"}->(), "\n"; # a:3 b:8 print "a:", $a->{"pop"}->(), " b:", $b->{"pop"}->(), "\n"; # a:2 b:7 print "a:", $a->{"pop"}->(), " b:", $b->{"pop"}->(), "\n"; # a:1 b:6 print "a:", $a->{"pop"}->(), " b:", $b->{"pop"}->(), "\n"; # a:0 b:5
クラスはクロージャと構造体の組み合わせ。