【发布时间】:2018-04-21 21:57:21
【问题描述】:
上下文
我正在尝试编写一个类系统,该系统将通过对音符和节奏进行排列来生成旋律。我将在“Renoise”软件的“xStream”工具中使用它。我这里的例子是我真正拥有的一个非常愚蠢和通用的版本。
我也将此作为一个学习机会。我的 OOP 技能很弱,而且我还没有完全理解元表。所以,如果我完全错过了一些东西,那么先发制人地抱歉。我正在按照Lua 编程第 3 版中基本 OOP 示例的样式编写所有代码。
我的问题
我想要做的是将具有类似功能的类方法全部分组到“嵌套”表中。例如,“旋律排列”表、“节奏排列”表、杂项实用方法表等。
在代码中,我有一个类SomeClass。它有两种类型的打印功能:print1_notes 在'主表'中(即SomeClass 的键)。 print2.notes 在“嵌套”表print2 中,这是SomeClass 的键(即notes 只是SomeClass.print2 的键)。
我可以打电话给print1_notes 就好了。问题是当我使用冒号运算符调用 print2 方法时。
如果我不使用糖(例如,obj.print2.notes(obj)),那么没问题。但是当我这样做时(例如,obj.print2:notes()),我收到有关“尝试(等等)一个函数值......”的错误。
- 如何在没有冒号运算符的情况下工作?
-
SomeClass.print2中的方法可以访问SomeClass中的键吗?它们是否具有与非嵌套表键相同的访问权限? - 我在想
print2需要一个__index键来告诉它的方法在不知道self.a_key是什么时查找SomeClass中的键。但是self(在print2方法中)不是关键。它实际上只是SomeClass的别名。是吗?似乎与嵌套表存在差异。 - 是否需要将 SomeClass 设为 print2 的元表?这是否可能,因为 print2 不是 SomeClass 的单独表?
- 我应该尝试不同的方法吗?也许多重继承?
谢谢。抱歉,如果这需要移动,或者之前有人问过这个问题。
我的代码
SomeClass = {
new = function (self, t)
t = t or {}
setmetatable(t, self)
self.__index = function (_, key)
return self[key]
end
--should I add a setmetatable here? perhaps:
--setmetatable(self.print2, self)
return t
end,
notes = {},
set_notes = function (self, t)
self.notes = t or {}
self.N = #self.notes
end,
print1_notes = function (self)
print("There are "..tostring(self.N).." notes :", table.unpack(self.notes))
end,
--table of different print functions
print2 = {
notes = function (self)
--is self an alias for SomeClass?
assert(self.notes, "Error: self.notes = nil")
print("There are "..tostring(self.N).." notes :", table.unpack(self.notes))
end,
first_note = function (self)
fn = self.notes[1]
print("first note is: ", fn)
end,
},
}
obj = SomeClass:new()
obj:set_notes{ 10,14,5, 10,14,5, 17 }
print("\ncalling print1_notes without sugar:")
obj.print1_notes(obj)
print("\ncalling print1_notes with sugar:")
obj:print1_notes()
print("\ncalling print2.notes without sugar")
obj.print2.notes(obj)
print("\ncalling print2.notes with sugar")
obj.print2:notes() --this gives an error: "attempt to get length of a function value"
obj.print2.first_note(obj) --this works fine
obj.print2:first_note() --this gives an error:
-- "attempt to index a function value (field 'notes')"
编辑代码:tostring(N) 的实例需要替换为 tostring(self.N)。
编辑:奇怪的错误与SomeClass.print2.notes 有一个像SomeClass.notes 这样的注释成员有关。 SomeClass.print2.first_note 避免了这种复杂性。 (我会在回答时解释更多)
编辑:我想出了一个解决方案。它不漂亮,但它有效。我将在下面发布我的答案。
【问题讨论】:
-
obj.print2:notes()是obj.print2.notes(obj.print2)的糖,而不是obj.print2.notes(obj)的糖 -
是的。我没有意识到这一点;我猜该手册不够详尽。谢谢。