Lua-オブジェクト指向

OOPの紹介

オブジェクト指向プログラミング(OOP)は、現代のプログラミングで使用されている最も使用されているプログラミング手法の1つです。OOPをサポートするプログラミング言語は多数あります。

  • C++
  • Java
  • Objective-C
  • Smalltalk
  • C#
  • Ruby

OOPの特徴

  • Class −クラスは、オブジェクトを作成するための拡張可能なテンプレートであり、状態(メンバー変数)の初期値と動作の実装を提供します。

  • Objects −これはクラスのインスタンスであり、それ自体に個別のメモリが割り当てられています。

  • Inheritance −これは、あるクラスの変数と関数が別のクラスに継承されるという概念です。

  • Encapsulation−クラス内でデータと関数を組み合わせるプロセスです。関数を使用して、クラスの外部からデータにアクセスできます。これは、データ抽象化とも呼ばれます。

LuaでのOOP

Luaのテーブルとファーストクラス関数を使用して、Luaでオブジェクト指向を実装できます。関数と関連データをテーブルに配置することにより、オブジェクトが形成されます。継承はメタテーブルの助けを借りて実装でき、存在しない関数(メソッド)と親オブジェクトのフィールドのルックアップメカニズムを提供します。

Luaのテーブルには、値に依存しない状態やIDなどのオブジェクトの機能があります。同じ値を持つ2つのオブジェクト(テーブル)は異なるオブジェクトですが、オブジェクトは異なる時間に異なる値を持つことができますが、常に同じオブジェクトです。オブジェクトと同様に、テーブルには、誰が作成したか、どこで作成されたかに依存しないライフサイクルがあります。

実際の例

オブジェクト指向の概念は広く使用されていますが、適切かつ最大の利益を得るには、それを明確に理解する必要があります。

簡単な数学の例を考えてみましょう。円、長方形、正方形など、さまざまな形で作業する状況に遭遇することがよくあります。

シェイプは、共通のプロパティAreaを持つことができます。したがって、共通のプロパティ領域を使用して、ベースオブジェクトの形状から他の形状を拡張できます。各形状は独自のプロパティを持つことができ、長方形のような関数は、プロパティとして長さ、幅、面積、関数としてprintAreaとcalculateAreaを持つことができます。

単純なクラスの作成

面積、長さ、幅の3つのプロパティを持つ長方形の簡単なクラス実装を以下に示します。また、計算された面積を印刷するためのprintArea関数もあります。

-- Meta class
Rectangle = {area = 0, length = 0, breadth = 0}

-- Derived class method 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

-- Derived class method printArea

function Rectangle:printArea ()
   print("The area of Rectangle is ",self.area)
end

オブジェクトの作成

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

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

プロパティへのアクセス

以下に示すように、ドット演算子を使用してクラスのプロパティにアクセスできます。

print(r.length)

メンバー関数へのアクセス

以下に示すように、オブジェクトでコロン演算子を使用してメンバー関数にアクセスできます。

r:printArea()

メモリが割り当てられ、初期値が設定されます。初期化プロセスは、他のオブジェクト指向言語のコンストラクターと比較できます。以上のように値を設定できる機能に他なりません。

完全な例

Luaでオブジェクト指向を使用した完全な例を見てみましょう。

-- Meta class
Shape = {area = 0}

-- Base class method 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

-- Base class method printArea

function Shape:printArea ()
   print("The area is ",self.area)
end

-- Creating an object
myshape = Shape:new(nil,10)

myshape:printArea()

上記のプログラムを実行すると、次の出力が得られます。

The area is 	100

Luaでの継承

継承は、形状などの単純なベースオブジェクトを長方形や正方形などに拡張するプロセスです。これは、基本的なプロパティと機能を共有および拡張するために、現実の世界でよく使用されます。

簡単なクラス拡張を見てみましょう。以下のようなクラスがあります。

-- Meta class
Shape = {area = 0}

-- Base class method 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

-- Base class method printArea

function Shape:printArea ()
   print("The area is ",self.area)
end

以下に示すように、形状を正方形のクラスに拡張できます。

Square = Shape:new()

-- Derived class method new

function Square:new (o,side)
   o = o or Shape:new(o,side)
   setmetatable(o, self)
   self.__index = self
   return o
end

基本関数のオーバーライド

基本クラスの関数を使用する代わりに、基本クラスの関数をオーバーライドできます。派生クラスは、以下に示すように独自の実装を持つことができます。

-- Derived class method printArea

function Square:printArea ()
   print("The area of square is ",self.area)
end

継承の完全な例

上記のように、メタテーブルを使用した別の新しいメソッドを使用して、Luaでの単純なクラス実装を拡張できます。基本クラスのすべてのメンバー変数と関数は、派生クラスに保持されます。

-- Meta class
Shape = {area = 0}

-- Base class method 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

-- Base class method printArea

function Shape:printArea ()
   print("The area is ",self.area)
end

-- Creating an object
myshape = Shape:new(nil,10)
myshape:printArea()

Square = Shape:new()

-- Derived class method new

function Square:new (o,side)
   o = o or Shape:new(o,side)
   setmetatable(o, self)
   self.__index = self
   return o
end

-- Derived class method printArea

function Square:printArea ()
   print("The area of square is ",self.area)
end

-- Creating an object
mysquare = Square:new(nil,10)
mysquare:printArea()

Rectangle = Shape:new()

-- Derived class method new

function Rectangle:new (o,length,breadth)
   o = o or Shape:new(o)
   setmetatable(o, self)
   self.__index = self
   self.area = length * breadth
   return o
end

-- Derived class method printArea

function Rectangle:printArea ()
    print("The area of Rectangle is ",self.area)
end

-- Creating an object

myrectangle = Rectangle:new(nil,10,20)
myrectangle:printArea()

上記のプログラムを実行すると、次の出力が得られます-

The area is 	100
The area of square is 	100
The area of Rectangle is 	200

上記の例では、基本クラスSquareからRectangleとSquareの2つの派生クラスを作成しました。派生クラスの基本クラスの関数をオーバーライドすることができます。この例では、派生クラスは関数printAreaをオーバーライドします。