Objective-Oriented Matlab

#なぜ書くか
MATLABで普段研究してる大学生なんですが、
コードをうだうだかき回すのキモいなって思って、
依存性は排除しつつもできるだけ使いまわせるように
MatlabでのOOPを試みてきました。
プログラミング歴まだ２年なので、色々試行錯誤してます。

Mathworks社の出しているリファレンスが残念ながら結構
わかりづらいのでここにまとめてみようと思います。

#Matlabの雰囲気
Matlabってなんだよ…初めて聞くよ…？？
って方のために、簡単に言語としてのイメージを伝えると、
Matlab = (Ruby+Python+Java)/3;
です。
オブジェクト指向で書けるしパッケージがあって、
でもクラスの書き方はRuby+Pythonで、、、
といった雰囲気です。

行列計算とグラフ出力が標準で組み込まれているため
統計解析を用いた研究などをする際に多く使われています。

#目次
* パッケージの作り方と呼び出し方
* クラスの作り方
* インスタンス化
* オブジェクト配列の作り方
* 申し訳程度に抽象クラスの作り方

#パッケージの作り方と呼び出し方
名前空間が衝突しないようにパッケージで
階層を設けるのは、Javaに顕著な特徴かと思うのですが、
Matlabでもそれが可能です。
`./libs/+Common/Utility.m`
`./libs/+Common/Figure.m`
例えば上記のようにUtility, Figureのモジュールを
作成してフォルダを組むと、
Commonパッケージが作成されます。
このlibsディレクトリとそのサブディレクトリにパスを通せば
`util = Common.Utility;`
などとして呼び出せます。

# クラスの作り方
クラスのファイルと、それを呼び出すファイルの
例を作ってみます。

```matlab:Utility.m
classdef Utility
　properties(Constant)
　　FontSizeVal = 16;
　　FontSize = 'FontSize';
　end
　methods(Static)
　　function DirName = setResultDir(NewDir)
　　　% @desc: method to create a new directory where result files are saved.
　　　% @input: NewDir: NewDirectory Name, for example '2014-11-02-NewDir'
　　　DirName = ['./results/' NewDir];
　　　mkdir(DirName);
　　end
　end
end
```

こういうモジュールファイルを作ってみて、
呼び出して使ってみます。

```matlabsession
util = Utility;
DirName = util.setResultDir('2014-11-02-New-Directory');
```

これが、初歩的な(というか原始的な？)クラスの使い方。
関連する複数の関数を１つのファイルに書いておくことが出来ます。
この形態は、モジュールて言うと思います。

# インスタンス化
インスタンス化する（モジュールではない）
一般的な「クラス」については、
handleクラスを継承してあげる必要があります。

あんまり詳しいことは読んでいないんですが、
インスタンスとして値を保持し続けるには
handleクラスの継承が必要みたいです。
下記がサンプルコード。
[引用元](http://stackoverflow.com/questions/12140152/matlab-getter-setter-methods-why-do-they-make-my-program-super-slow)のを修正しています。

```matlab:sensorlocest.m
classdef sensorlocest < handle 
    properties(GetAccess = public, SetAccess = private)
        x;
        y;
    end
 
    methods
        function sensors = sensorlocest(x,y)
            if nargin ~= 0
               sensors.x = x*rand;
               sensors.y = y*rand;
            end
        end
        function init(sensors,x,y)
            sensors.x = x*rand;
            sensors.y = y*rand;
        end
        function set.x(sensors,newx)
            sensors.x = newx;
        end
        function set.y(sensors,newy)
            sensors.y = newy;
        end
    end
end
```
下記で確認。

```matlabsession
rehash;
lo = sensorlocest(1,2);
 
lo.init(10, 20);
lo.x
  => {random number}
lo.x = 1;
lo.x
  => 1
```

さり気なくsetter/getterを突っ込んでいますが、
今回は割愛します。

# オブジェクト配列の作り方

##Case1: 自身を配列にする場合
コンストラクタで自身を配列にするクラスを
作りたい場合はこちらをご参照ください。

```matlab:child.m
classdef child < handle
　properties(SetAccess=private,GetAccess=public)
　　age;
　end
　methods
　　function c = child(age)
　　　if nargin ~=0
　　　　c(5, 1) = child;
　　　　for I=1:length(c),
　　　　　c(I).age = age;
　　　　end
　　　end
　　end
　end
end
```
動作確認：

```matlabsession
children = child(20);
children(1).age
=> 20
children(2).age
=> 20
```

ここでのポイントは、
childクラスのコンストラクタにて

```matlabsession
if nargin ~=0
end
```
をセットしているところです。これにより、
引数無しでもそのクラスを呼び出すことができるようになります。

**具体的には、**

```matlabsession
c(5,1) = child;
```
が実行可能となっています。ここ、if nargin ~=0, ** end
がない場合には、引数が足りなくて実行できないといった
エラーにつながります。

Matlabではchildとchild()（引数なし）が
同じ意味を持つので、これは重要です。

##Case2: 別のオブジェクトをプロパティとして持つ場合
デザインパタンを使っていく際にはコチラが
必要となってくると思います。

子クラスを親クラスの中のプロパティに
配列として呼び出すケース。
さっき作ったchildクラスも書き換えて使います。

```matlab:child.m
classdef child < handle
　properties(GetAccess=public, SetAccess=public)
　　name;
　　age;
　end
　methods
　　function c = child
　　　if nargin ~=0
　　　　% write process which runs when the input exists
　　　end
　　end
　　function set.age(c, age)
　　　c.age = age;
　　end
　　function set.name(c, name)
　　　c.name = name;
　　end
　end
end
```

```matlab:parent.m
classdef parent < handle
　properties
　　% give a data type
　　children = child;
　end
　methods
　　function p = parent(NumberChildren)
　　　% set object-ed array to children property
　　　p.children(NumberChildren, 1) = child;
　　end
　end
end
```
この例では、parentクラス内のpはparentオブジェクトとなり、
そのプロパティであるchildrenが動的に作成される
childのオブジェクト配列になっています。

```matlabsession
p = parent(3);
length(p.children)
=> 3
p.children(1).name = 'James';
p.children(1).name
=> James
```

# 申し訳程度に抽象クラスの作り方
これも本丸で、今回実はBuilderパタンていうのを
実装してまして、抽象クラスについても調べました。

```matlab:Builder.m
classdef(Abstract) Builder < handle
　methods
　　% never write the initializer in Abstract class

　　% write only output and input.
　　% "function", "end" and so on are not permitted.
　　construct
　end
end
```

継承するときは、他の言語と同様に次のように書いてください。
抽象クラスで書いてあるメソッドを実装しないと、
エラーが発生します。

また、継承先をインスタンス化する場合には、
継承元の抽象クラスにてhandleクラスを
継承しておく必要があります。
抽象クラスに**< handle**と書くだけです。

```matlab:ConcreteBuilder.m
classdef ConcreteBuilder < Builder
　methods
　　function conctruct()
　　　% implement this method here!
　　end
　end
end
```

こんな感じすかね。
必要に応じて記事アップデートします。

#参考
[setterとgetterについての記事](http://loudspeaker.sakura.ne.jp/devblog/2014/10/31/oop-matlab-setter-getter-example/)