Google Apps Scriptでクラス構文を掻甚する【GAS】

V8 Runtime察応になったGoogle Apps Scriptですが、長幎ES5での制限を受けおきた故に、りェブ䞊でのコヌド玹介でも殆どが平打の関数を構築しお呌び出すずいった事による、原始的なコヌド蚘述も倚く、たたラむブラリの堎合ワンクッション入るせいか実行が遅いずいうこずで、コヌドの再利甚性などが積極的に進んでいない珟状がありたす。

元々倧芏暡開発等ではGASは䜿わないずいう面もありたすが、無理しおクラスを䜿わなくおも十分なアプリを構築可胜であるため小芏暡が倚い為䜿うたでもない、スルヌされがちです。今回はV8から䜿えるようになったクラスに぀いお、䜿い所や実際の珟堎で䜿うようなシヌンを想定しお掘っおみたいず思いたす。事前に以䞋の゚ントリヌのClass構文も読んでおくず良いでしょう。

※自分自身は、GASに぀いおはES2019たでは察応しおるのを確認しおいたすが、ES2022たでは調べおいないですが、2020の新メ゜ッドは䜿えなかったので珟状はES2022のClass FieldsやPrivate Property, Static倉数などのクラスの新機胜は䜿えたせん。

Google Apps ScriptのV8 Runtime察応を怜蚌しおみた

今回䜿甚するサンプルファむル

Google Apps Scriptでクラス構文を䜿うためには、「V8ランタむム」はオンにしおおく必芁がありたす。プロゞェクト蚭定を開き、「Chrome V8 ランタむムを有効にする」にチェックを入れたしょう。以前はV8ランタむムでクラスを利甚するず非垞に遅いずいう事があったのですが、珟圚は解消されおいる暡様です。

今回は固定資産の枛䟡償华を蚈算するシヌトでclassを䜿っおみたいず思いたす。珟時点ではES2019蟺りたでの仕様は䜿えるみたいで、プラむベヌトフィヌルドやプロパティなどのES2022からの仕様などぱラヌずなり䜿えたせん。

※珟圚、ファむルの䜍眮に関係なく定矩したクラスは利甚出来るので、クラスのファむルよりも䞋で呌び出さないず゚ラヌになるずいった珟象はありたせん。

図V8ランタむムで利甚が可胜になりたす。

クラスの䜿い所

関数のみでは駄目なのか

単玔なスクリプトであるならば、Classを䜿うメリットは殆どありたせんが、ある皋床の芏暡のプログラムになっおくるず、堪える。ずいう話をよく聞きたす。関数をいく぀も䜜っお、それを呌び出しおプログラムを䜜るずいうスタむルでは䜕故堪えるのかずいう芖点で考えたす。

今回のテヌマのように固定資産の枛䟡償华だず、個々の固定資産が持っおる情報はすべお必芁でありながら、䞭身が異なっおいたす。償华期間であったり、償华法、取埗原䟡等。これらを回すにあたっお、関数だけで行う堎合、スプレッドシヌトずの読み曞きが頻繁に発生する事ずなるため、倧きなグロヌバル倉数で配列を甚意しお、そこにこれらの蚭定倀プロパティを甚意しお、個ず぀栌玍が必芁になりたす。

さらに枛䟡償华にた぀わる様々な関数や凊理、珟圚の蚭定倀の取埗等をするにあたっおも、それらを考慮する必芁がありたす。

この時、蚭定の塊を぀のテンプレヌトずしお甚意し、そこにた぀わる専甚の関数をメ゜ッドチェヌンで呌び出したりする為に䜿うのがクラスです。Google Apps ScriptだずGASで甚意された各皮クラスを皆さん普段から䜿っおいたりしたすJSのnew Date()もクラスず蚀えたす。

new Classでむンスタンスずいうのを䜜るずこのテンプレヌトの塊が定矩されお、個々に償华期間や償华法、原䟡取埗がそれぞれ定矩、それを凊理する関数はclassを枡しお䞊げればより簡単に凊理が出来るわけです。

クラスの䞭身はどうなっおるのか

枛䟡償华の堎合、個々の固定資産の持぀情報や様々な蚈算方法などを䞀塊にしたものを甚意するわけですが、情報は倚岐に枡る䞊に償华法が異なる等、実際にこれをスプレッドシヌトを䜿っお、幎毎に資産毎に読み曞きをしおるず非垞に煩雑になっおしたいたす。

クラスの基本的な構造は以䞋の芁玠で成り立っおいたす

基本䞭の基本

クラスを䜜るずなった堎合にたずは䞀番倖偎を䜜りたす。そしおそれを、new classnameにお個々にむンスタンスずいうものを䜜っおから倉数に栌玍。その倉数に察しお、メ゜ッドチェヌンで関数を呌び出したり、呜什を䞎えるず蚈算結果や珟圚の倀が返っおくるずいう仕組みになっおいたす。

コンストラクタ

必ず定矩する必芁のあるのが、コンストラクタ。むンスタンスを䜜成する時に匕数で受け取っお、個々の芁玠のプロパティずいうものを栌玍しおおくものです。ここに、固定資産の各皮倀を入れおおく事が可胜です。個別の資産毎に䜜成したす。

たた、ただ匕数で受け取っお栌玍するだけでなく、蚈算をしお初期倀を栌玍する事も可胜。以䞋の事䟋では償华補償額を匕数では受けずに、取埗䟡額 × 保蚌率で蚈算しお、this.hosyouに栌玍しおいたす。コンストラクタ内に定矩した倉数はパブリックになりたす。var _test = 0.5みたいな曞き方でプラむベヌト颚に出来たすが、コンストラクタ内でだけしか䜿えないです。

※コンストラクタの倖偎にグロヌバルプロパティを䜜る事は出来たせん

この時、倉数assetに栌玍された内容をconsole.logで出力するず以䞋のようになりたす。asset.s_nenずしお出力すれば償华幎数の倀を取埗する事が可胜になりたす。逆に、asset.kagaku = 2000000ずしお実行すれば、プロパティの倀を倉曎する事が可胜です。

関数を定矩する

クラスで利甚する関数を定矩する事が可胜です。クラス内に存圚するthisの倉数を利甚し、匕数を取っお蚈算する仕組みを䜜っおみたす。getAssetNameずいう関数を定矩しお、資産名を取り出しお返すだけの関数です。

asset.getAssetName()におこの関数が呌び出されお、プロパティの倀を取埗する事が可胜です。

staticメ゜ッド

倉動するこずの無い予め栌玍しおおいた倀を返す為だけに利甚するタむプで利甚するもので、staticず付けお関数を定矩するだけです。ただし、thisが䜿えない為、プロパティ等にはアクセスが出来たせん。ちょっず倉わった芁玠ず蚀えたす。

今回は3匹のモンスタヌを定矩し、それぞれのむンスタンスを生成。それらの持぀経隓倀の平均を取る為のstaticメ゜ッドで蚈算しお返すずいうものを䜜っおみたした。

このように、thisでコンストラクタ内のプロパティを利甚しお蚈算する為のものずいうよりも、クラス自身が持っおるナヌティリティな機胜ずしお実装する堎合に䜿うずいった感じです。故にクラスですが通垞のラむブラリのメ゜ッドのような動きをする、そのクラス特化の関数を栌玍しおおくものずしお定矩するず良いでしょう。そのため、むンスタンス化せず、いきなりmonster.avgExp()ずしお利甚できたす。

蚈算結果ずしおは、3668が返っおきたす。

プラむベヌトプロパティ颚な手法

Google Apps Scriptの堎合、珟時点ではコンストラクタの倖偎に倉数定矩をしたり、クラス内郚でだけ利甚するプラむベヌトプロパティを利甚する事が出来たせん。そのため、コンストラクタ内の倉数には簡単にアクセス出来る反面、簡単に曞き換えも出来おしたう為、安党面では難がありたす。

しかし、以䞋の即時関数 + Symbol  + クラスを利甚した堎合には、倖郚からの倀を栌玍埌には簡単に曞き換えも出来ないようにする事が可胜です。次項のセッタヌを䜿ったりゲッタヌを䜿わないず取埗できないように制限を課すこずが可胜なので、この手法はGASでクラスを䜿う堎合には必須のテクニックかもしれたせん。

  • クラスを即時関数で囲っおおく即時関数の倉数名ずクラス名は䞀臎させおおく
  • 即時関数内ならば、グロヌバルで倉数を定矩出来る
  • ただし盎接倉数名を定矩しお倀を栌玍するのではなく、Symbolを䜿っお固有のIDを生成しおおく。
  • クラス内のコンストラクタではthis[Symbolの倉数]にお、プロパティを定矩し、コンストラクタの匕数がむンスタンス生成時の匕数になる
  • ゲッタヌであるItemNameを䜿わないず盎接栌玍された情報にアクセスは出来たせん。セッタヌに぀いおも同じ。
  • 倉数を呌び出す時も、this[Symbolの倉数]にお呌び出し、蚈算しおreturnすれば蚈算結果ずしお返すこずは可胜です。
  • 䞊蚘に斌いおconsole.logの出力結果は以䞋の通りになりたす。console.logで倉数名だけだず䜕も出力されず、たたitem.nameずしおもコンストラクタの倉数に栌玍した倀は取れたせん。

この仕組を䜿うず、倖郚から途䞭の倉数を取埗したりが䞍可胜になるので、䟋えばOAuth2.0認蚌のAccess Tokenの取埗であったり、その暗号化・埩号化ずいった凊理をクラスに䜜り蟌めば隠蔜できるので、安党性も高たりたす。

図理想の圢で倀の取埗を制埡出来た

ゲッタヌずセッタヌ

通垞、コンストラクタに定矩したプロパティの内容は、䟋えばitem.nameずいったものや、item.getName()ずいった圢で簡単に取埗する事が可胜です。逆を行えば倀をセットするこずも可胜。なので、敢えおゲッタヌやセッタヌずいう仕組みを䜿甚せずずも、目的の凊理は実珟できたすが、前述のように入力制限を課しおるクラスの堎合は盎接倀を取埗できたせん。

そこで getやsetずいう文字を付けた関数を甚意する事で、それぞれ倀の取埗、倀の曞き換えを実珟するようにコヌドを組み、ゲッタヌずセッタヌからしかアクセスさせないようにすれば、より安党なクラスを䜜る事が可胜です。ただし、コンストラクタ内のプロパティは読み曞きが出来おしたうので、䞀床栌玍したら倉曎できないようにする堎合は、䞊蚘のコヌドで蚀えばセッタヌで参照させなければOKです。

※アクセッサプロパティず総称されるこずもありたす。

ゲッタヌにお、item.nameずしおも前述の手法の堎合、プロパティの倀は取埗できたせん。必ずゲッタヌを経由しおitem.ItemNameずしお参照しないず取埗が出来ない。同様にセッタヌを経由しないず、item.name = “お塩”ずしおも、倀は曞き換わりたせん。

クラスの継承

クラスは1床定矩したら基本的にはその構造を倉曎する事が出来たせん。しかし、䟋えば固定資産の枛䟡償华のクラスを定矩した埌に、それらず共通するような内容αの「瀟甚車クラス」ずいうものを定矩したくなったら、別個に䜜らなければならないずなるず、もったいない瀟甚車だっお枛䟡償华する。

ずいうこずで䞋敷きになる「枛䟡償华クラス」をベヌスに、瀟甚車クラスを䜜っお機胜を远加しおみたいず思いたす。ただし、継承⇒継承ず継承しすぎおわけが分からなくなるような運甚は蟞めたしょう。

extendsで継承

extendsは、芪ずなるクラスに察しお、関数などの機胜を远加する堎合に利甚したす。そのため、新芏にコンストラクタを定矩したりは出来たせん。新たに継承で定矩したクラスでは、芪のクラスを利甚し぀぀、远加した関数で挔算させるずいった事が可胜になりたす。

䞊蚘のコヌドでは、assetman2ずいう芪ずなるクラスを定矩し぀぀、継承するsyayoucarをextends assetman2で継承しおいたす。このクラスからむンスタンスを生成し、asset.resale()を実行するず、きちんず取埗䟡額×1.2の金額が蚈算されお返っおきたす。

芪のクラスでむンスタンスを生成しおいない点ずコンストラクタが無い点がポむント。芪のクラスでむンスタンスを生成しおも、resale関数は圓然実行されたせん。新たにコンストラクタを定矩しおしたうず、芪のコンストラクタが消えおしたいたす。

superでオヌバヌラむド

前述のextendsの堎合、新たにコンストラクタを远加出来ないので、関数等の機胜の远加だけしか出来たせん。芪のコンストラクタに新芏に远加し぀぀ずいった堎合には、オヌバヌラむドず呌ばれる継承を利甚したす芪のクラスを䞊曞きするクラス。今回のケヌスだずこちらのほうが目的に合っおいたす。

芪に加えお、走行距離であったり修理費甚などずいったプロパティを加えおみたいず思いたす。

  • syayoucar2クラスで、assetman3を継承し぀぀、super()にお芪のコンストラクタも継承する
  • 必ず先にsuper()で継承しおから、远加のコンストラクタを定矩しないず、゚ラヌになる
  • syayoucar2のコンストラクタの匕数は芪の分独自の分を定矩しおおくruntotalずrepairecostを远加しおる
  • 芪の関数を呌ぶ堎合は、super.関数名()にお呌び出す事が出来る
  • 䞊蚘の関数だずasset.resaleにお1,224,000が答えずしお返っおきたす。

旧匏のクラスの定矩

V8ランタむムではない以前のGoogle Apps Scriptで動䜜出来るクラスのようなものずしお䜿われおいたコヌドは以䞋の通りES5準拠。Class構文は䜿えない為、即時関数ずPrototypeを利甚しお同じような仕組みを実珟しおいたした。

どうしおも、V8ランタむムでコヌドを蚘述できないようなケヌスでは䞊蚘のようなスタむルでクラスを実珟するようにしなければなりたせん。䞊蚘のコヌドでmon1.getHitpointで返っおくる倀は、245が返っおきたす。

枛䟡償华クラスのコヌドず解説

゜ヌスコヌド

コヌドの解説

  • 固定資産シヌトの資産䞀芧のデヌタを読み取っお、指定の幎数分の償华額合蚈を蚈算し、償华額シヌトにたずめお結果を出すクラスです
  • プロンプトにお償华幎数を取埗しお蚈算しおいたす。
  • s_typeの倀を元に定額法ず定率法で呌び出す関数を分岐しおいたす。
  • asset.calcretにお蚈算をさせお、償华額トヌタルを返しおもらっおいたす。
  • デヌタは䞀括で二次元配列にお曞き出しを行っおいたす。
  • calcretからは償华方法に応じお同じクラス内の別の関数をthis.関数名(匕数)にお枡しおいたす。

実際に構築しおみた結果ですが、これを単玔に関数でやっおしたうず、非垞に冗長なものになっおしたったり、埌でメンテナンスをする際に関数の手盎しが非垞に面倒になる点です。

呌び出し元のコヌドは非垞にシンプルになり、呌び出し先のクラスは郚品単䜍で现かく管理が出来る。これがクラスの利点になりたす。今回のような倧きな機胜になりそうなものは、いきなりコヌドで曞き始めるずいうよりは、クラスの蚭蚈をしお埌から機胜の远加をしおいくスタむルで䜜成すれば、機胜远加も容易になるず思いたす。

ゲヌムのように倧量に同じパタヌンを生成しお、それらを配列に栌玍し、1タヌン毎に各むンスタンスにランダムなパラメヌタを枡すなんお芞圓は、クラスが無いずずっちらかっお倧倉なこずになりたす。

図枛䟡償华蚈算がサクっず出来たした。

メ゜ッドチェヌンを䜜成する

応甚線ずしお、今回のような自䜜のクラスでメ゜ッドチェヌンを䜜る手法がありたす。GASでもよく芋かけるSpreadsheetApp.getActiveSpreadsheet().getSheetByName(“test”)みたいな圢で呜什を数珠぀なぎにしお送り蟌むものです。クラスを甚意できれば、これを構築する事が可胜です。

以䞋のコヌドは課皎額15%を䞊乗せし、利益を20%乗せお、最埌に答えを取埗するずいう䞀連のクラスを甚意しおメ゜ッドチェヌンずする手法です。

  • builder倉数ではクラスを初期化するコヌドだけを甚意しおおきたす。
  • クラス内では、取り敢えずコンストラクタの倀は0で初期化しお甚意しおおき、぀なげる関数からの匕数で入力する
  • ポむントは各関数は最埌倀を返すのではなく、thisだけを返すようにしたす。
  • 最終的な倀を取埗するgetSalesPriceのみ、答えをreturnで返すようにしおありたす。
  • chainmethodではbuilderをスタヌトずしお数珠぀なぎに2぀の関数を呌び出し、最埌に答えをもらっおいたす。tomatoには䞊蚘のコヌドならば、4140ずいう答えが返っおきたす。
  • それぞれの段階の倀を保持しおおけるのがクラスの良い点です。

関連リンク

コメントを残す

メヌルアドレスが公開されるこずはありたせん。

このサむトはスパムを䜎枛するために Akismet を䜿っおいたす。コメントデヌタの凊理方法の詳现はこちらをご芧ください。