我来自Python背景,我试图理解Ruby与Python的多重继承相比如何。具体来说,我使用相同的方法设置了两个模块,以了解super
的工作原理。
我包括Mod
,然后是Mod2
,然后是Mod
。但是,A
似乎仍在引用Mod2
。
module Mod
def foo(x)
x**2
end
end
module Mod2
def foo(x)
x*2
end
end
class A
include Mod
def foo(x)
super(x) + 1
end
end
A.new.foo(5) == 26 # true
class A
include Mod2
def foo(x)
super(x) + 1
end
end
A.new.foo(5) == 11 # true
class A
include Mod
def foo(x)
super(x) + 1
end
end
A.new.foo(5) == 26 # false. Is 11
为什么不是第三个A.new.foo(5)
返回26
?
答案 0 :(得分:1)
在Python中定义class A(object)
创建一个type
type
和__name__
A
的对象,然后将该对象分配给标签{{1} }。第二个A
定义创建一个全新的class A(object)
对象,然后将其放入标签A中。
ruby中的类不存储在标签中,可以打开它们以添加更多功能。一个很好的例子是type
。 Rails在整数上定义2.days
。如果没有Rails,days
会失败。
上面的3个类定义大致相当于:
2.days
当ruby看到第二个class A
include Mod
def foo(x)
super(x) + 1
end
include Mod2
def foo(x)
super(x) + 1
end
include Mod
def foo(x)
super(x) + 1
end
end
时,它知道include Mod
已经包含在课程中并跳过它,从Mod
开始foo
作为最新定义。
如果您从以后的定义中移除Mod2
,foo
仍然可以访问它:
A
答案 1 :(得分:1)
我认为你可能缺少的是第二个Option Explicit
Randomize
Dim conn, rst, query, fname, lname, CustID
CustID = 000276
'1
query = "SELECT * FROM [Report$] WHERE [ID]= '" & CustID & "'"
'2
query = "SELECT * FROM [Report$] WHERE [ID]= '000276' "
Set conn = CreateObject("ADODB.Connection")
conn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=db2.xlsx;" & _
"Extended Properties='Excel 12.0 Xml;HDR=Yes';"
Set rst = CreateObject("ADODB.Recordset")
rst.Open query, conn
If rst.EOF Then
fname = "[NO RECORDS]"
lname = "[NO RECORDS]"
Else
fname = rst("First Name").Value
lname= rst("Last Name").Value
End If
MsgBox("First Name is: " & fname & " and Last Name is: " & lname)
没有重新定义课程,它正在添加它。你被允许打开"一个类在ruby中多次并且(重新)定义你想要的任何东西。那,以及你似乎已经想到的,class A ... end
或多或少只是将代码从模块中删除到类定义中的那个位置,除非该模块已被包含在这种情况下它是什么都没有。
你可以在任何课程中做到这一点(无论是否可取)
include
答案 2 :(得分:0)
Ruby通过一次在类/模块的祖先链中搜索一个类/模块来找到super
,直到找到它正在寻找的方法的定义。有点像一辆有很多站点的公共汽车,寻找合适的下车地点,但它总是在第一次机会下车。如果它一直到BasicObject
并且没有找到它会停止它会引发NoMethodError
。
当您包含模块时,您将其添加到包含类/模块上方的祖先链中。你可以通过调用Module.ancestors
按顺序找到祖先。你可以多次包含同一个模块,但它只会被添加到祖先链一次。考虑一下:
module Mod
def foo(x)
x**2
end
end
module Mod2
def foo(x)
x*2
end
end
class A
include Mod
def foo(x)
super(x) + 1
end
end
A.ancestors # => [A, Mod, Object, Kernel, BasicObject]
class A
include Mod2
def foo(x)
super(x) + 1
end
end
A.ancestors # => [A, Mod2, Mod, Object, Kernel, BasicObject]
class A
include Mod
def foo(x)
super(x) + 1
end
end
A.ancestors # => [A, Mod2, Mod, Object, Kernel, BasicObject]
Mod
第二次被包括在血统链中,所以没有新的事情发生。保持不变,super
仍然首先点击Mod2
。简而言之,你无法覆盖"更新的模块,包括已经存在的旧模块。你可以做其他事情。您可以使用与Mod3
中相同的ModOverride
定义来定义foo
或Mod
,并将其包括在内,或者查看优化Ruby 2.0 How do I uninclude a module out from a module after including it? < / p>
正如其他答案所指出的那样,如果定义保持不变,则每次都不需要重新定义A#foo
。