見出し画像

【PhotoshopJavaScript】AdobeExtendScriptで疑似的にクラスを作る

スクリプトを開発していると、どうしても関数間で込み入った情報を受け渡す必要が出てきます。処理したいファイルのリスト、入力したい文字のリスト、接頭辞は何にするか、日付、ほげ、ふが…………

このような込み入った情報はObjectでのやりとりをしたいもの。でもでもでも、込み入ったObjectを場当たり的に作っていくと

{
fileList:{1:hoge.jpg,2:hufa.jpg},
textList:{1:"hoge",2:"huga"},
prefix:"pre_"
}

みたいな感じのブツができあがり、開発直後はまだ構造を覚えて居られたとしても、数年してから修正しようと思ったときに泣きを見ます。

そう、今の私のようにね!

というわけで、そんなときはclassのしくみを使って、オブジェクトの中に必要な情報を押し込んじゃえば楽ちん!!!!

なんですが、ExtendScriptくんはベースになってるjsのバージョンが古いために「class」が使えません。うそやろ。

というわけで、Objectを使って擬似的にクラスを再現してみます。

なんでクラスを使うと便利なのか

……については上記の記事で説明していますが、もうひとつ、「(クラス自体を適切に設計していれば)データの構造が可視化される」というメリットがあるなと今回気付きました。

オブジェクト(連想配列)を愚直に作っていると

var sample_object = {}

for(var key in nanikano_hairetsu){
    sample_object[key] = nanikano_hairetsu[key];
} 

// 何か別の処理が長々入る…………

sample_object["prefix"] = "pre_";

// また何か別の処理が…… 

というような記述がコードのあちこちに入り込んでしまい、最終的にどういう構造のオブジェクトが帰ってきているのかが一目では分かりません。

コメントでメモしておく手もあり、実際その手法を採用してたんですが、今度はどこにメモしたか解らなくなったり、メモした後で構造が変わったのにメモが直ってなかったりと、あまり実用的ではありませんでした。

しかし、擬似的にクラスを作っておくことで、

function nanika_no_data(hoge,huga){
    this.hoge = hoge;
    this.huga = huga;
    this.hogehoge = hoge + huga;
    this.setHoge = func_gethoge(this.hoge);
    
    const func_sethoge = function(x){ this.hoge =  x; }
    // SETメソッド作るなという話は横に置いておく
}

という記述がコード内に残るので、「ああ、nanika_no_dataオブジェクトにはhogeとhugaとhogehogeっていうパラメータと、setHogeっていうメソッドがあるんね」と一目でわかります。これほんと便利。

functionを使って擬似的にクラスを作る

細かい機序は正直よく分かってないんですが、classの代わりにfunctionを使って擬似的にクラスっぽいものを作り、インスタンスも作ることができます。(「ES5 クラス」とかで検索するともうちょっと詳しい説明が手に入ります)

function sample_class(x,y){
    this.x = x
    this.y = y
}

var sample_object = new sample_class(1,2);

基本の書き方はこれだけです。通常の関数と同じように引数を受け取ったら、this.を付けた変数に入れておきます。

そして、インスタンスを作る(実際にデータを入れる)時には、newを付けて呼びだし、保存しておきたい値を引数として渡します。

こうしておくと、

$.writeln(sample_object.x)

のように、保存しておいた値にアクセスできます。

これだけなら

{x:1,y:2}

という連想配列を作っても同じ事なのですが、前述の通り、オブジェクトの構造が可視化して残るというのが大きな違いです。これだけでもめちゃくちゃ楽になります。

値を加工してからthis.のとこにしまう

たとえば、ファイルのパスを受け取って、親フォルダ名とファイル名と拡張子を取り出して、それぞれ変数に保存してすぐアクセスできるようにしておきたい、とか。

プレーンテキストを受け取って、特定の記号で分割して配列化してから保存しておきたいとか。

そんなときは、

function sample_class(text){
    this.plain_text = text;
    this.list = split_text(text);
    
    function split_text(target_text){
        return target_text.split(",")
    }
}

ってな具合に関数を挟んで受け取ることも可能です。

メソッドを持たせる

だいたいここまでの内容で事足りますが、例えば内部にさらに連想配列をもっていて、そのキーに対応する値を取り出したいとか。(連想配列使うのが嫌だから疑似クラス作ってるんですけど、一次元の単純な連想配列くらいなら、そのまま持っててもそこまでややこしくはならないかなって)

あと、外部から受け取った数値と比較して真偽値返したいとか。

そんなときはメソッドを持たせると便利です。

var fruit = { a: "apple", b: "banana", c: "cherry"}

function sample_class(object){
    this.object = sample_object;
    this.get_value = function(key){return this.object[key]};
    this.is_exist = function(key){return this.object.hasOwnProperty(key)};
}

var sample_object = sample_class(fruit);
$writeln(sample_object.get_value("a")) // apple

通常のクラスとはちょっとメソッドの持たせ方が違いますが、this.チームの中に関数代入した変数置いとけばOKです。

「データと、それにまつわる操作」をひとまとめにしておけるのがクラスの利点です。これでひとまず、およそクラスらしいものを作ることができました。やったね。


この記事が気に入ったらサポートをしてみませんか?