HOME Sather を試そう 書き込む

10. 変更不能クラス


1. はじめに

一度生成されると変更できないインスタンスを生成するクラスを immutable class といいます。 組み込みクラスの中では BOOL, CHAR, INT, FLT, FLTD などが immutable class です。

2. immutable class の例

2次元の座標 POINT を immutale class として定義してみましょう。[code 1] のようになります。 インスタンスは変更不能なので、属性に値を代入する方法が通常のクラスと異なっています。

[code 1]

01:     -- a simple immutable class
02:     
03:     immutable class POINT < $STR is   -- class の前に immutable をつけて変更不能であることを宣言します。
04:        readonly attr x,y:FLT;         -- x,y の2つの readonly 属性を宣言します。
05:     
06:        create(x0,y0:FLT):SAME is      -- 初期化の方法が普通のクラスと違います。
07:           res:SAME;                   -- new を使ってメモリー領域を確保する必要はありません。
08:           res:=res.x(x0);             -- immutable class では属性に値を代入するのはこのようにします。
09:           res:=res.y(y0);
10:           return res;
11:        end;
12:     
13:        is_eq(p:SAME):BOOL is          -- オペレータ '=' を定義します。
14:           return x=p.x and y=p.y;
15:        end;
16:     
17:        plus(p:SAME):SAME is           -- オペレータ '+' を定義します。
18:           return #SAME(x+p.x, y+p.y);
19:        end;
20:     
21:        minus(p:SAME):SAME is          -- オペレータ '-' を定義します。
22:           return #SAME(x-p.x, y-p.y);
23:        end;
24:     
25:        times(n:FLT):SAME is           -- オペレータ '*' を定義します。
26:           return #SAME(x*n, y*n);
27:        end;
28:     
29:        div(n:FLT):SAME is             -- オペレータ '/' を定義します。
30:           return #SAME(x/n, y/n);
31:        end;
32:     
33:        negate:SAME is                 -- 単項演算子 '-' を定義します。
34:           return #SAME(-x, -y);
35:        end;
36:     
37:        abs:FLT is
38:           return (x*x+y*y).sqrt;
39:        end;
40:     
41:        rotate(theta:FLT):SAME is       -- 原点を軸とした回転を定義します。
42:           theta := y.atan2(x)+theta;
43:           return #SAME(self.abs*theta.cos, self.abs*theta.sin);
44:        end;
45:     
46:        str:STR is                      -- 文字列への変換を定義します。
47:           return "(" + x.str +"," + y.str +")";
48:        end;
49:     end;
50:     
51:     class MAIN is
52:        const pi:FLT:= FLT::pi;         -- 円周率を定義します。
53:        const fout:STR:="point.out";    -- 出力用ファイルの名前です。
54:     
55:        rz_polygon(a:ARRAY{POINT}, zoom, theta:FLT):ARRAY{POINT} is  -- 多角形を zoom して 回転します。
56:           a1:ARRAY{POINT}:=#(a.size);
57:           loop
58:     	 a1.set!(a.elt!.rotate(theta).times(zoom));
59:           end;
60:           return a1;
61:        end;
62:     
63:        out2file(a0,a1:ARRAY{POINT}) is           -- ズームして回転する前と後の多角形をファイルに出力します。
64:           f:FILE:=FILE::open_for_write(fout);
65:           p0,p1:POINT;
66:           i:INT;
67:           loop
68:     	 i:=(a0.size+1).times!;
69:     	 if i = a0.size then i:=0; end;
70:     	 p0:=a0[i];
71:     	 p1:=a1[i];
72:     	 f + p0.x + "\t" + p0.y + "\t" + p1.x + "\t" + p1.y + "\n";
73:           end;
74:           f.close;
75:        end;
76:     
77:        main is
78:           p0:POINT:=#(0.0,1.0);
79:           a0:ARRAY{POINT}:=#(3);
80:     
81:           loop                            -- (0.0, 1.0) を 0, 120, 240 度回転して正三角形を作ります
82:     	 a0.set!(p0.rotate(3.times!.flt*2.0*pi/3.0));
83:           end;
84:           
85:           out2file(a0, rz_polygon(a0, 2.0, pi/12.0));  -- 元の正三角形と2倍に拡大して 15 度回転した正三角形をファイルに書き出します。
86:           
87:        end;
88:     end;
結果を gnuplot で書き出すと 図1のようになります。

図 1:もともとの正三角形と2倍に拡大して 15 度回転した正三角形          

3. 終わりに

immutable class は通常のクラスより効率的に処理されます。従って、たくさんのインスタンスを生成するクラスは immutable class に したほうが速度面で有利になります。

HOME Sather を試そう 書き込む