English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Lua オブジェクト指向

オブジェクト指向プログラミング(Object Oriented Programming、OOP)は非常に人気のあるコンピュータプログラミングアーキテクチャです。

以下のいくつかのプログラミング言語はオブジェクト指向プログラミングをサポートしています:

  • C++

  • Java

  • Objective-C

  • Smalltalk

  • C#

  • Ruby

オブジェクト指向の特徴

  • 1)封装:ある実体の情報、機能、応答を独立したオブジェクトに収めることができる特性です。

  • 2)継承:継承の方法は、元のプログラムを変更せずに拡張するために使用されます。これにより、元の機能が保存され、新機能も拡張されます。これにより、コードの重複を減らし、ソフトウェア開発の効率を向上させます。

  • 3)多態:同じ操作が異なるオブジェクトに適用されると、異なる解釈が行われ、異なる実行結果が得られます。実行時には、基底クラスのポインタを通じて、派生クラス内のメソッドを呼び出すことができます。

  • 4)抽象:抽象(抽象化)は複雑な現実問題を簡素化する手段であり、具体的な問題に対して最適なクラス定義を見つけることができ、最適な継承レベルで問題を解釈することができます。

Luaのオブジェクト指向

私たちは、オブジェクトは属性とメソッドで構成されていることを知っています。LUAでは最も基本的な構造はテーブルであり、したがって、オブジェクトの属性を説明するためにテーブルを使用する必要があります。

Luaのfunctionはメソッドを表すために使用できます。したがって、LUAのクラスはテーブルを通じて表されます。 + functionでシミュレートできます。

継承はmetatableでシミュレートできます(推奨しませんが、基本的なオブジェクトをシミュレートするのに十分なことが多いです)。

Luaでのテーブルはある意味ではオブジェクトでもあります。オブジェクトのように、テーブルにも状態(メンバ変数)があり、また独立した性質を持ち、異なる値を持つオブジェクト(テーブル)は異なるオブジェクトを表します。オブジェクトは異なる時期に異なる値を持つこともありますが、常に同じオブジェクトです。オブジェクトと同様に、テーブルのライフサイクルはそれがどこで作成され、どのように作成されたかに関係ありません。オブジェクトにはメンバ関数があり、テーブルにもあります:

Account = {balance = 0}
function Account:withdraw(v)
    Account.balance = Account.balance - v
end

この定義は、新しい関数を作成し、Accountオブジェクトのwithdraw領域に保存します。以下のように呼び出すことができます:

Account.withdraw(100.00)

簡単な例

以下の簡単なクラスには3つの属性があります:area、length、breadth、printAreaメソッドは計算結果を表示するために使用されます:

-- メタクラス
Rectangle = {area = 0, length = 0, breadth = 0}
-- 派生クラスのメソッド new
function Rectangle:new (o,length,breadth)
  o = o or {}
  setmetatable(o, self)
  self.__index = self
  self.length = length or 0
  self.breadth = breadth or 0
  self.area = length*breadth;
  return o
end
-- 派生クラスのメソッド printArea
function Rectangle:printArea ()
  print("長方形の面積 ",self.area)
end

オブジェクトの作成

オブジェクトの作成は、クラスの例にメモリを割り当てるプロセスです。各クラスには独自のメモリがあり、共有データを共有します。

r = Rectangle:new(nil,10,20)

属性のアクセス

クラスの属性にアクセスするために、ピリオド(.)を使用できます:

print(r.length)

メンバ関数のアクセス

クラスのメンバ関数にアクセスするために、コロン(:)を使用できます:

r:printArea()

メモリはオブジェクトが初期化されたときに割り当てられます。

完全な例

以下では、Luaのオブジェクト指向の完全な例を示します:

-- メタクラス
Shape = {area = 0}
-- 基本クラスメソッド new
function Shape:new(o, side)
  o = o or {}
  setmetatable(o, self)
  self.__index = self
  side = side or 0
  self.area = side*side;
  return o
end
-- 基本クラスメソッド printArea
function Shape:printArea()
  print("面積 ",self.area)
end
-- オブジェクトの作成
myshape = Shape:new(nil,10)
myshape:printArea()

上記のプログラムを実行すると、以下の結果が表示されます:

面積は     100

Luaの継承

継承とは、一つのオブジェクトが別のオブジェクトの属性とメソッドを直接使用することです。これにより、基本クラスの属性とメソッドを拡張できます。

以下に簡単な継承例を示します:

-- メタクラス
Shape = {area = 0}
-- 基本クラスメソッド new
function Shape:new(o, side)
  o = o or {}
  setmetatable(o, self)
  self.__index = self
  side = side or 0
  self.area = side*side;
  return o
end
-- 基本クラスメソッド printArea
function Shape:printArea()
  print("面積 ",self.area)
end

次の例では、Square オブジェクトが Shape クラスを継承しています:

Square = Shape:new()
-- 派生クラスメソッド new
function Square:new (o,side)
  o = o or Shape:new(o,side)
  setmetatable(o, self)
  self.__index = self
  return o
end

完全な例

以下の例では、派生クラスのメソッドを拡張するために簡単なクラスを継承しました。派生クラスでは、継承クラスのメンバ変数とメソッドが保持されます:

-- メタクラス
Shape = {area = 0}
-- 基本クラスメソッド new
function Shape:new(o, side)
  o = o or {}
  setmetatable(o, self)
  self.__index = self
  side = side or 0
  self.area = side*side;
  return o
end
-- 基本クラスメソッド printArea
function Shape:printArea()
  print("面積 ",self.area)
end
-- オブジェクトの作成
myshape = Shape:new(nil,10)
myshape:printArea()
Square = Shape:new()
-- 派生クラスメソッド new
function Square:new (o,side)
  o = o or Shape:new(o,side)
  setmetatable(o, self)
  self.__index = self
  return o
end
-- 派生クラスメソッド printArea
function Square:printArea ()
  print("正方形の面積 ",self.area)
end
-- オブジェクトの作成
mysquare = Square:new(nil,10)
mysquare:printArea()
Rectangle = Shape:new()
-- 派生クラスメソッド new
function Rectangle:new (o,length,breadth)
  o = o or Shape:new(o)
  setmetatable(o, self)
  self.__index = self
  self.area = length * 幅
  return o
end
-- 派生クラスメソッド printArea
function Rectangle:printArea ()
  print("長方形の面積 ",self.area)
end
-- オブジェクトの作成
myrectangle = Rectangle:new(nil,10,20)
myrectangle:printArea()

上記のコードを実行すると、出力結果は以下の通りです:

面積は     100
正方形の面積は     100
長方形の面積は     200

関数オーバーライド

Luaでは、基底クラスの関数をオーバーライドし、派生クラスで独自の実装方法を定義できます:

-- 派生クラスメソッド printArea
function Square:printArea ()
  print("正方形の面積 ",self.area)
end