第1版はLua5.0向けに書かれました。後のバージョンでもほとんど関連性はありますが、いくつかの違いがあります。
第4版はLua5.3を対象にしており、Amazonおよびその他書店で購入できます。
書籍を購入することで、Luaプロジェクトのサポートにも貢献できます。
![]() |
Programming inLua | ![]() |
第II部.テーブルとオブジェクト 第16章.オブジェクト指向プログラミング |
オブジェクトのプライバシーは、オブジェクト指向言語にとって不可欠な部分であると多くの人が考えています。各オブジェクトの状態は、それ自体が内部的に処理すべきものです。C++やJavaなどのOO言語では、オブジェクトのフィールド(インスタンス変数とも呼ばれます)やメソッドがオブジェクト外から見えるかどうかを制御できます。Smalltalkなどの他の言語では、すべての変数をプライベートにして、すべてのメソッドをパブリックにしています。最初のOO言語であるSimulaには、一切の保護機能はありませんでした。
以前に説明した、Luaにおけるオブジェクトのメイン設計には、プライバシー機能がありません。これは、オブジェクトの表現に一般的な構造(テーブル)を使用しているためでもあります。しかし、これはLuaの基本的な設計思想も反映されています。Luaは、多くのプログラマーが長期間にわたって関わるような大規模なプログラムを構築することを目的としていません。それとは逆に、Luaは通常大規模システムの一部である、小規模から中規模のプログラムを目標にしており、通常は1人のプログラマー、または数人のプログラマー、さらにはノンエンジニアによって開発されています。したがって、Luaでは不要な冗長性や人工的な制約を避けています。オブジェクト内の何かへのアクセスしたくない場合は、単にアクセスしないでください。
それでも、Luaのもう1つの目標は柔軟性であり、プログラマーに、さまざまなメカニズムをエミュレートできるメタメカニズムを提供することです。Luaにおけるオブジェクトの基本設計にはプライバシー機能はありませんが、アクセス制御を実現するために、オブジェクトを別の方法で実装できます。この実装は頻繁に使用されるものではありませんが、Luaの興味深い部分を探索するため、そして他の問題に対する有効な解決策になり得るため、知っておくことが有益です。
この代替設計の基本的な考え方は、オブジェクトを、状態用のテーブルと操作またはインターフェイス用のテーブルの2つのテーブルで表現することです。オブジェクト自体には、2番目のテーブル、つまりインターフェイスを構成する操作を通じてアクセスします。不正アクセスを避けるため、オブジェクトの状態を表すテーブルは、他のテーブルのフィールドには保持されません。代わりに、メソッドのクロージャ内にのみ保持されます。たとえば、この設計で銀行口座を表すには、次のファクトリ関数を起動して新しいオブジェクトを作成できます。
function newAccount (initialBalance) local self = {balance = initialBalance} local withdraw = function (v) self.balance = self.balance - v end local deposit = function (v) self.balance = self.balance + v end local getBalance = function () return self.balance end return { withdraw = withdraw, deposit = deposit, getBalance = getBalance } end最初に、この関数は内部オブジェクトの状態を保持するためのテーブルを作成し、それをローカル変数の
self
に格納します。次に、オブジェクトの各メソッドに対して、クロージャ(つまり、ネストした関数のインスタンス)を作成します。最後に、メソッド名を実際のメソッド実装にマッピングする外部オブジェクトを作成して返します。重要な点は、これらのメソッドはself
を追加パラメータとして取得しないことです。代わりに、self
に直接アクセスします。追加引数がないため、コロン構文を使用してそのようなオブジェクトを操作することはありません。メソッドは他の関数とまったく同じように呼び出されます。acc1 = newAccount(100.00) acc1.withdraw(40.00) print(acc1.getBalance()) --> 60
この設計では、self
テーブルに格納されたすべての情報を完全にプライベートにします。newAccount
が戻った後、そのテーブルに直接アクセスする方法はありません。newAccount
内で作成された関数からのみアクセスできます。この例ではプライベートテーブルにインスタンス変数が1つだけ格納されていますが、そのテーブルにオブジェクトのプライベート部分をすべて保存することができます。プライベートメソッドを定義することもできます。これはパブリックメソッドに似ていますが、インターフェイスには配置しません。たとえば、アカウントでは特定の制限を超える残高を持つユーザーに追加の10%のクレジットを与えることもできますが、ユーザーはこの計算の詳細にアクセスできるようにすることはできません。この実装は次のようになります。
function newAccount (initialBalance) local self = { balance = initialBalance, LIM = 10000.00, } local extra = function () if self.balance > self.LIM then return self.balance*0.10 else return 0 end end local getBalance = function () return self.balance + self.extra() end ...繰り返しますが、ユーザーが
extra
関数に直接アクセスすることはできません。Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved. | ![]() |