local B = {} -- in real life there is other stuff in B
B.Object = {
constructor = function() end,
extend = function(this, that, meta)
if not that then that = {} end
if not meta then meta = {} end
meta.__index = this
setmetatable(that, meta)
return that
end,
isa = function(this, that)
for meta in function() return getmetatable(this) end do
if this == that then return true end
this = meta.__index
end
return this == that
end,
new = function(this, ...)
local that = this:extend()
that:constructor(...)
return that
end,
}
所有对象(包括“类对象”)都直接或间接扩展了
B.Object
。例如: -- Request handler base
B.RequestHandler = B.Object:extend()
-- override these
function B.RequestHandler:accept() error "not implemented" end
function B.RequestHandler:process() error "not implemented" end
-- URL-encoded POST handler
B.PostHandler_URLEncoded = B.RequestHandler:extend()
function B.PostHandler_URLEncoded:accept()
return self.method == "POST" and
self.content_type == "application/x-www-form-urlencoded"
end
function B.PostHandler_URLEncoded:process()
-- some code
end
-- Multipart POST handler
B.PostHandler_Multipart = B.RequestHandler:extend()
-- etc.
它可能会被这样使用:
B.request_handlers = {
GetHandler:new(),
URLEncodedPostHandler:new(),
MultipartPostHandler:new(),
}
B.handle_request = function()
for k, v in ipairs(B.request_handlers) do
if v:accept() then
return v:process()
end
end
error "request not handled"
end
据我所知,这几乎是Lua中处理继承的正常方法。我想念什么吗?有什么需要改进的吗?
#1 楼
示例用法您提供的示例并没有真正帮助解释代码应如何工作。我相信它确实可以工作,但是变量并不完全匹配。例如,下面的代码是:
B.request_handlers = {
GetHandler:new(),
URLEncodedPostHandler:new(),
MultipartPostHandler:new(),
}
什么在此之前是
B.request_handlers
?您可以像在前面的代码块中那样定义“类”:B.RequestHandler = B.Object:extend()
,但现在它是小写字母并带有下划线。这些括号内的三个电话的情况相同。 GetHandler
叫什么?我在任何地方都找不到匹配的方法。只是有点混乱。缺少注释
第一个代码块是最重要的代码块,因为这是您建立实际Lua继承的地方。代码的问题在于它非常密集,并且没有任何关于预期如何使用的解释。
例如,您定义如下的extend方法:
extend = function(this, that, meta)
if not that then that = {} end
if not meta then meta = {} end
meta.__index = this
setmetatable(that, meta)
return that
end,
,但是在您的示例中,您可以这样称呼它:
B.RequestHandler = B.Object:extend()
阅读完该方法后,我可以理解如果调用
extend()
时不带任何参数,则参数将填充在方法内部。我认为发表评论解释调用extend
方法的有效方法将非常有帮助。在大多数语言中,当方法具有参数时,必须提供它们,否则编译器会抱怨。由于Lua是一种动态语言,您将无法进行检查,因此我认为解释如何使用OOP实现的注释变得更加重要。 这个,那个和另一个
此代码很难理解:
isa = function(this, that)
for meta in function() return getmetatable(this) end do
if this == that then return true end
this = meta.__index
end
return this == that
end,
new = function(this, ...)
local that = this:extend()
that:constructor(...)
return that
end,
所有那个,那个,然后,这个==那个,返回那个,等等等等只会使我的大脑扭成一个结。如果我非常仔细地逐行阅读代码,最终我会弄不清楚它的作用,但是我认为这是代码的失败。
没错,您可能不打算让任何人阅读您的继承代码。相反,一旦设置完成,它将可以正常工作,并允许使用该代码的人以经典的OOP方式扩展对象。但是,我仍然认为,通过使用更好的变量名,一些注释和更多的代码行,可以这样编写它,以便在阅读时可以立即理解它。
也认为不是说英语的人可能会为此而感到困惑,那么then关键字对情况无济于事。
东西不错
我喜欢这段代码在这里:
-- override these
function B.RequestHandler:accept() error "not implemented" end
function B.RequestHandler:process() error "not implemented" end
该注释非常清楚,这些是应重写的方法,如果没有,将返回的字符串将使很清楚出了什么问题。
评论
我建议添加一些注释来描述您的代码的意图。最大的问题可能是私有财产。我前段时间尝试了一些想法,但是每个选项要么都非常不完整(因此将需要大量样板代码),要么将至少两个级别引入到调用堆栈中。所以我的建议是:尝试不继承。无需继承即可解决大多数代码复制问题。