どういうわけか、私はluaでOOPの征服に真剣に取り組みました。 そして、このトピックに関してインターネットで私が見つけたのは、この言語の優雅さに合わない下線が豊富な大量のコードだけでした。 そこで、簡単な解決策を探すことにしました。
たくさんのスマートブックを読み、OOPのいくつかのひどい実装を分析した後、私は、LUAでオブジェクト指向プログラミングの独自のスタイルを開発するまで、最も有用でシンプルなものを少しずつ収集しました。
クラスとインスタンスを作成する
クラスPerson
-- Person= {} -- function Person:new(fName, lName) -- local obj= {} obj.firstName = fName obj.lastName = lName -- function obj:getName() return self.firstName end -- ! setmetatable(obj, self) self.__index = self; return obj end -- vasya = Person:new("", "") -- print(vasya.firstName) --> : -- print(vasya:getName()) --> :
ご覧のとおり、すべてが非常に簡単です。 ドットの配置場所とコロンの場所が混同されている場合、ルールは次のとおりです:プロパティにアクセスする場合はドット(object.name)を配置し、メソッドの場合はコロン(object:getName())を配置します。
もっと面白い。
ご存じのとおり、OOPは継承、カプセル化、および多態性の3つの柱に基づいています。 同じ順番で「報告」を行います。
継承
前のクラス(Person)から継承したクラスを作成する必要があるとします。
クラスの女性
Woman = {} -- setmetatable(Woman ,{__index = Person}) -- masha = Woman:new("","") print(masha:getName()) --->:
すべてうまくいきますが、私は個人的にこの継承オプションが嫌いです。 したがって、私はグローバル拡張()関数を作成するだけです。
拡張()
function extended (child, parent) setmetatable(child,{__index = parent}) end
これで、クラスの継承がよりきれいになります。
クラスの女性
Woman = {}; -- extended(Woman, Person) -- masha = Woman:new("","") print(masha:getName()) --->:
カプセル化
これまでのクラスのプロパティとメソッドはすべてパブリックでしたが、プライベートなプロパティとメソッドも簡単に作成できます。
クラスPerson
Person = {} function Person:new(name) local private = {} -- private.age = 18 local public = {} -- public.name = name or "" -- "" - -- function public:getAge() return private.age end setmetatable(public,self) self.__index = self; return public end vasya = Person:new() print(vasya.name) --> : print(vasya.age) --> : nil print(vasya:getAge()) --> : 18
ほら すべてはあなたが慣れているものとほとんど同じです。
多型
ここではまだ簡単です。
多型
Person = {} function Person:new(name) local private = {} private.age = 18 local public = {} public.name = name or "" -- , function public:getName() return "Person protected "..self.name end -- , function Person:getName2() return "Person "..self.name end setmetatable(public,self) self.__index = self; return public end -- , Person Woman = {} extended(Woman, Person) -- -- function Woman:getName() return "Woman protected "..self.name end -- getName2() function Woman:getName2() return "Woman "..self.name end -- masha = Woman:new() print(masha:getName()) --> Person protected print(masha:getName2()) --> Woman
ここで何をしましたか?
-2つのメソッドgetName()およびgetName2()を使用してPersonクラスを作成しました。最初のメソッドはオーバーライドから保護されています。
-Womanクラスを作成し、Personクラスから継承しました。
-Womanクラスの両方のメソッドを再定義しました。 最初のものは再定義されていません。
-利益を得た!
ところで、パブリックメソッドはクラス本体の外部でも定義できます。
多型
Person = {} function Person:new(name) local private = {} private.age = 18 local public = {} public.name = name or "" -- , function public:getName() return "Person protected "..self.name end setmetatable(public,self) self.__index = self; return public end -- , function Person:getName2() return "Person "..self.name end
しかし、再定義した基本クラスのメソッドを呼び出す必要がある場合はどうでしょうか? これも簡単にできます!
構文は次のとおりです。ParentClass.Method(object_name、パラメーター(存在する場合))。
クラスの女性
-- , Person Woman = {} extended(Woman, Person) -- -- setName function Woman:getName2() return "Woman "..self.name end print(masha:getName2()) --> Woman -- print(Person.getName2(masha)) --> Person
追記
以上で、少なくともこの記事が役に立つことを心から願っています。
最後に、完全なコードを提供します。IDEでコードをコピーし、動作することを確認できます。
完全なコード
function extended (child, parent) setmetatable(child,{__index = parent}) end Person = {} function Person:new(name) local private = {} private.age = 18 local public = {} public.name = name or "" -- , function public:getName() return "Person protected "..self.name end -- function Person:getName2() return "Person "..self.name end setmetatable(public,self) self.__index = self; return public end -- , Person Woman = {} extended(Woman, Person) -- -- setName function Woman:getName2() return "Woman "..self.name end masha = Woman:new() print(masha:getName2()) --> Woman -- print(Person.getName2(masha)) --> Person