国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

[Lua] 實現(xiàn)所有類的基類Object、模擬單繼承OO、實現(xiàn)抽象工廠

這篇具有很好參考價值的文章主要介紹了[Lua] 實現(xiàn)所有類的基類Object、模擬單繼承OO、實現(xiàn)抽象工廠。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

所有類的基類 Object

Lua 沒有嚴(yán)格的 oo(Object-Oriented)定義,可以利用元表特性來實現(xiàn)

先定義所有類的基類,即Object類。代碼順序從上到下,自成一體。完整代碼

定義一個空表 Object ,__index 指向其自身(繼承將直接使用該表作為對象的元表)

Object = {}
Object.__index = Object

new 定義構(gòu)造對象時的初始化行為,相當(dāng)于構(gòu)造器?;惒恍枰M行任何初始化操作

function Object:new()
end

extend 實現(xiàn)了類繼承,具體流程

  • 創(chuàng)建一個空表 cls,作為類
  • 我們將父類的元方法全部復(fù)制給子類 ?為什么
  • 子類的 __index 指向其自身(子類可被繼承)(覆蓋了父類復(fù)制給子類的 __index
  • 子類的 super 字段指向父類
  • 子類的元表指向父類(子類)
function Object:extend()
  local cls = {}
  for k, v in pairs(self) do
    if k:find("__") == 1 then
      cls[k] = v
    end
  end
  cls.__index = cls
  cls.super = self
  setmetatable(cls, self)
  return cls
end

implement 用于實現(xiàn)接口類,可傳入多個接口

  • 遍歷每個接口 cls
  • 當(dāng)前對象如果沒有實現(xiàn)接口類的某個方法,則將該方法的實現(xiàn)從接口類復(fù)制給對象
function Object:implement(...)
  for _, cls in pairs({ ... }) do
    for k, v in pairs(cls) do
      if self[k] == nil and type(v) == "function" then
        self[k] = v
      end
    end
  end
end

is用于判斷某個類或?qū)ο髮嵗欠袷橇硪粋€類

  • 循環(huán)拿元表,直到?jīng)]有為止,最后一個元表一定是 Object
function Object:is(T)
  local mt = getmetatable(self)
  while mt do
    if mt == T then
      return true
    end
    mt = getmetatable(mt)
  end
  return false
end

__tostring 用于對象 printtostring 時自定義字符串化

function Object:__tostring()
  return "Object"
end

直接用類名稱,來實現(xiàn)一個對象的實例化。__call 可以把變量當(dāng)函數(shù)使用,比如Car類(變量),local mycar = Car(),生成了一個對象實例myCar,屬于類Car

  • 創(chuàng)建一個對象(空表),并把自身(類)作為對象的元表
  • 執(zhí)行構(gòu)造器,由于對象是空表找不到,所以通過元表的__index也就是去父類找
  • 返回初始化好的對象實例
function Object:__call(...)
  local obj = setmetatable({}, self)
  obj:new(...)
  return obj
end

全局函數(shù) unrealized用于模擬接口或抽象類未定義的方法,子類未實現(xiàn)時會寄

function unrealized(...)
  error("未實現(xiàn)", 2)
end

到現(xiàn)在為止已經(jīng)模擬了一個單繼承OO,在需要的地方導(dǎo)入模塊,使用 Objectunrealized 這兩個全局變量


實驗-抽象工廠

接下來實現(xiàn)抽象工廠模式。抽象工廠能創(chuàng)建一系列相關(guān)的對象,而無需指定其具體類。

考慮如下情況,有多類敵人(正方形、圓形、長條),敵人初始化是兩種狀態(tài)的一種(正常狀態(tài),厚血狀態(tài)),且后期敵人和狀態(tài)種類還會增多

我們先定義敵人抽象類

Enemy = Object:extend()

Enemy.draw = unrealized
Enemy.new = function(self)
  self.hp = 100
end

然后定義繼承抽象類Enemy的抽象類SquareEnemy,與繼承抽象類SquareEnemy的兩個普通類SquareEnemyWhite、SquareEnemyRed。圓形敵人跟長條敵人同理。

SquareEnemy = Enemy:extend()
SquareEnemy.new = function(self, x, y, w)
  SquareEnemy.super.new(self)
  self.x = x
  self.y = y
  self.w = w
end

SquareEnemyWhite = SquareEnemy:extend()
SquareEnemyWhite.draw = function(self)
  love.graphics.setColor(1, 1, 1)
  love.graphics.rectangle("fill", self.x, self.y, self.w, self.w)
end

SquareEnemyRed = SquareEnemy:extend()
SquareEnemyRed.new = function(self, ...)
  SquareEnemyRed.super.new(self, ...)
  self.hp = 200
end
SquareEnemyRed.draw = function(self)
  love.graphics.setColor(1, 0, 0)
  love.graphics.rectangle("fill", self.x, self.y, self.w, self.w)
end

定義工廠接口,在這里接口算是一種特殊的抽象類(由于只能用表來模擬接口,所以讓接口也繼承Objcet)

IFactory = Object:extend()

IFactory.circleEnemy = unrealized
IFactory.squareEnemy = unrealized
IFactory.barEnemy = unrealized

分別實現(xiàn)白色工廠和紅色工廠(如果沒有額外的創(chuàng)建操作,可以不用return)

WhiteFactory = Object:extend()
WhiteFactory:implement(IFactory)

WhiteFactory.circleEnemy = function(...)
  return CircleEnemyWhite(...)
end

WhiteFactory.squareEnemy = function(...)
  return SquareEnemyWhite(...)
end

WhiteFactory.barEnemy = function(...)
  return BarEnemyWhite(...)
end

RedFactory = Object:extend()
RedFactory:implement(IFactory)

RedFactory.circleEnemy = function(...)
  return CircleEnemyRed(...)
end

RedFactory.squareEnemy = function(...)
  return SquareEnemyRed(...)
end

RedFactory.barEnemy = function(...)
  return BarEnemyRed(...)
end

接下來測試抽象工廠

require 'oo'
require 'enemy.aac'
require 'enemy.bar'
require 'enemy.circle'
require 'enemy.square'
require 'factory.aac'
require 'factory.red_factory'
require 'factory.white_factory'

enemies = {}
love.load = function()
  IFactory = WhiteFactory()
  table.insert(enemies, IFactory.circleEnemy(100, 100, 25))
  table.insert(enemies, IFactory.squareEnemy(100, 200, 25))
  table.insert(enemies, IFactory.barEnemy(100, 300, 10, 50))
  IFactory = RedFactory()
  table.insert(enemies, IFactory.circleEnemy(200, 100, 25))
  table.insert(enemies, IFactory.squareEnemy(200, 200, 25))
  table.insert(enemies, IFactory.barEnemy(200, 300, 10, 50))
  for _, enemy in pairs(enemies) do
    print(enemy.hp)
  end
end

love.draw = function()
  for _, enemy in ipairs(enemies) do
    enemy:draw()
  end
end

參考資料

  • 《Lua程序設(shè)計·第四版》羅伯托·耶魯薩林斯希 、第227~241頁

其它

oo.lua

Object = {}
Object.__index = Object

function Object:new()
end

function Object:extend()
  local cls = {}
  for k, v in pairs(self) do
    if k:find("__") == 1 then
      cls[k] = v
    end
  end
  cls.__index = cls
  cls.super = self
  setmetatable(cls, self)
  return cls
end

function Object:implement(...)
  for _, cls in pairs({ ... }) do
    for k, v in pairs(cls) do
      if self[k] == nil and type(v) == "function" then
        self[k] = v
      end
    end
  end
end

function Object:is(T)
  local mt = getmetatable(self)
  while mt do
    if mt == T then
      return true
    end
    mt = getmetatable(mt)
  end
  return false
end

function Object:__tostring()
  return "Object"
end

function Object:__call(...)
  local obj = setmetatable({}, self)
  obj:new(...)
  return obj
end

function unrealized(...)
  error("未實現(xiàn)", 3)
end

-- return Object

QUESTION1

如果不復(fù)制元方法,假設(shè)類B繼承類A,類B的對象實例b,b的元表是類B,在調(diào)用 b + b 時,涉及到算術(shù)運算符相關(guān)的元方法,b會在父類B中查找__add,找不到并不會順著B的元表__index再去B的父類A找,因此會報錯

A = {
  __index = A,
  __add = function(a, b)
    return a.age + b.age
  end,
  name = "小白"
}
B = { __index = B, }
b = { __index = b, age = 1 }

setmetatable(B, A)
setmetatable(b, B)

print(b.name)
print(b + b)
--[[
> dofile 'TEST/test.lua'
小白
TEST/test.lua:15: attempt to perform arithmetic on a table value (global 'b')
stack traceback:
        TEST/test.lua:15: in main chunk
        [C]: in function 'dofile'
        stdin:1: in main chunk
        [C]: in ?
]]

點我返回文章來源地址http://www.zghlxwxcb.cn/news/detail-671329.html


到了這里,關(guān)于[Lua] 實現(xiàn)所有類的基類Object、模擬單繼承OO、實現(xiàn)抽象工廠的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • C++的基類和派生類構(gòu)造函數(shù)

    C++的基類和派生類構(gòu)造函數(shù)

    基類的成員函數(shù)可以被繼承,可以通過派生類的對象訪問,但這僅僅指的是普通的成員函數(shù),類的構(gòu)造函數(shù)不能被繼承。構(gòu)造函數(shù)不能被繼承是有道理的,因為即使繼承了,它的名字和派生類的名字也不一樣,不能成為派生類的構(gòu)造函數(shù),當(dāng)然更不能成為普通的成員函數(shù)。

    2024年02月10日
    瀏覽(21)
  • 如何用IDEA查看一個類的所有繼承關(guān)系

    如何用IDEA查看一個類的所有繼承關(guān)系

    最近在研究集合的繼承關(guān)系圖,在網(wǎng)上查的都不是很全,所以就想能不能直接看jar包里面的以來關(guān)系,在網(wǎng)上查了一下方法,總結(jié)如下: 工具:idea 功能:diagram 在你想查看的類內(nèi),點擊右鍵,選擇 Diagrams,其中有 show Diagrams和 show Diagrams Popup,前者新建在標(biāo)簽頁內(nèi),后者以浮

    2024年02月04日
    瀏覽(23)
  • Vue3實現(xiàn)組件級基類的幾種方法

    Vue3的組件有三種代碼組織方式 純Option API (不含setup) option API + setup 純 setup (即composition API) 對于這三種形式,設(shè)置基類的方法也略有不同。 vue3提供了 mixins和extends,但是嘗試之后發(fā)現(xiàn)這兩種方法只支持純OptionAPI,設(shè)置的data會被識別,但是設(shè)置的setup里return 的 reactive,完

    2024年02月01日
    瀏覽(22)
  • 作為所有類的頂層父類,沒想到Object的魔力如此之大!

    作為所有類的頂層父類,沒想到Object的魔力如此之大!

    在上一篇博文中我們提到了Java面向?qū)ο蟮乃拇筇匦?,其中談及“抽象”特性時做了一個引子,引出今天的主人公Object,作為所有類的頂級父類,Object被視為是James.Gosling的哲學(xué)思考,它高度概括了事務(wù)的自然與社會行為。 跟進Object類的源碼中我們可以看到,類的注釋中對它做

    2024年02月01日
    瀏覽(20)
  • Unity UGUI的Outline(描邊)組件的介紹及ABP框架提供的增刪改查的基類使用

    Outline(描邊)組件是Unity UGUI中的一種特效組件,用于給UI元素添加描邊效果。通過設(shè)置描邊的顏色、寬度和模糊程度,可以使UI元素在視覺上更加突出。 Outline(描邊)組件通過在UI元素周圍繪制多個相同的UI元素,并設(shè)置不同的顏色和大小,從而實現(xiàn)描邊的效果。描邊的寬度和模糊

    2024年02月21日
    瀏覽(19)
  • C++ | 繼承(基類,父類,超類),(派生類,子類)

    文章參考:https://blog.csdn.net/war1111886/article/details/8609957 一 .繼承中的訪問權(quán)限關(guān)系 1.基類,父類,超類是指被繼承的類,派生類,子類是指繼承于基類的類.? 2.在C++中使用: 冒號表示繼承,如class A : public B;表示派生類A從基類B繼承而來 3.派生類包含基類的所有

    2024年02月15日
    瀏覽(60)
  • 基類與派生類對象的關(guān)系 派生類的構(gòu)造函數(shù)

    基類與派生類對象的關(guān)系 派生類的構(gòu)造函數(shù)

    ??博主主頁: @??. 一懷明月?? ????? 專欄系列: 線性代數(shù),C初學(xué)者入門訓(xùn)練,題解C,C的使用文章,「初學(xué)」C++ ?? 座右銘: “不要等到什么都沒有了,才下定決心去做” ??????大家覺不錯的話,就懇求大家點點關(guān)注,點點小愛心,指點指點?????? 目錄 ??

    2023年04月10日
    瀏覽(23)
  • effective c++ 43-處理模板化基類的名稱 筆記

    該節(jié)主要分析了一個寫模板時常常會遇到的一個編譯錯誤。 這里有一個模板基類,有派生類繼承了模板基類,并調(diào)用了基類中的方法,但是編譯器卻會報找不該方法,這是怎么回事? 編譯輸出如下: 從編譯的輸出也可以看出,原因是編譯器覺得 sendClear 含義不明確,編譯器

    2024年02月03日
    瀏覽(29)
  • 【Unity之IMGUI】—位置信息類和控件基類的封裝

    【Unity之IMGUI】—位置信息類和控件基類的封裝

    ?????個人主頁 :@元宇宙-秩沅 ????? hallo 歡迎 點贊?? 收藏? 留言?? 加關(guān)注?! ????? 本文由 秩沅 原創(chuàng) ????? 收錄于專欄 : 缺點1:無法在編譯過程進行可視化調(diào)整 缺點2:無法分辨率自適應(yīng) 作用:讓控件根據(jù)調(diào)整對齊 最終代碼 特點: 類是抽象類:原因基類

    2024年02月12日
    瀏覽(26)
  • 基于C/C++將派生類賦值給基類的詳細(xì)講解

    目錄 將派生類對象賦值給基類對象 將派生類指針賦值給基類指針

    2024年02月08日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包