Ruby方法查找(与JavaScript比较)
我想更好地理解Ruby中的对象如何在类和模块中定义访问方法。具体来说,我想将其与JavaScript(我更熟悉JavaScript)进行比较和对比 在JavaScript中,对象在对象本身上查找方法,如果在那里找不到,它将在原型对象上查找方法。此过程将继续,直到到达Ruby方法查找(与JavaScript比较),javascript,ruby,inheritance,prototypal-inheritance,Javascript,Ruby,Inheritance,Prototypal Inheritance,我想更好地理解Ruby中的对象如何在类和模块中定义访问方法。具体来说,我想将其与JavaScript(我更熟悉JavaScript)进行比较和对比 在JavaScript中,对象在对象本身上查找方法,如果在那里找不到,它将在原型对象上查找方法。此过程将继续,直到到达Object.prototype // JavaScript Example var parent = { someMethod: function () { console.log( 'Inside Parent' );
Object.prototype
// JavaScript Example
var parent = {
someMethod: function () {
console.log( 'Inside Parent' );
}
};
var child = Object.create( parent );
child.someMethod = function () {
console.log( 'Inside Child' );
};
var obj1 = Object.create( child );
var obj2 = Object.create( child );
obj1.someMethod(); // 'Inside Child'
obj2.someMethod(); // 'Inside Child'
在JavaScript示例中,obj1
和obj2
都没有对象本身的someMethod
函数。需要注意的关键是:
child
对象中有一个someMethod
函数的副本,并且obj1
和obj2
都委托给child
对象obj
和obj2
在对象本身上都没有someMethod
函数的副本子对象
没有定义someMethod
函数,则委托将继续到父对象
# Ruby Example
class Parent
def some_method
put 'Inside Parent'
end
end
class Child < Parent
def some_method
puts 'Inside Child'
end
end
obj1 = Child.new
obj2 = Child.new
obj1.some_method # 'Inside Child'
obj2.some_method # 'Inside Child'
#Ruby示例
班级家长
定义某些方法
把“放在父母里面”
结束
结束
类子<父
定义某些方法
把“孩子里面”
结束
结束
obj1=Child.new
obj2=Child.new
obj1.some_方法#“内部子对象”
obj2.some_方法#“内部子对象”
以下是我的问题:
obj1
和obj2
是否各自拥有some\u方法的副本?或者它与JavaScript类似,在JavaScript中,两个对象都可以通过另一个对象(在本例中,通过子类)访问some_方法
我的直觉告诉我,Ruby对象没有从类继承的、混合在模块和超类中的方法的单独副本。相反,我的直觉是Ruby处理方法查找的方式与JavaScript类似,在JavaScript中,对象检查对象本身是否有方法,如果没有,则在对象的类中查找方法,混合在模块中,和超类,直到查找到达
BasicObject
让我们在IRB会话中继续使用您的示例,看看我们可以学到什么:
> obj1.method(:some_method)
=> #<Method: Child#some_method>
> obj1.method(:some_method).source_location
=> ["(irb)", 8]
> obj2.method(:some_method)
=> #<Method: Child#some_method>
> obj2.method(:some_method).source_location
=> ["(irb)", 8]
>obj1.method(:some_方法)
=> #
>obj1.方法(:某些方法)。源位置
=>[“(内部评级)”,8]
>obj2.方法(:某些方法)
=> #
>obj2.method(:某些方法)。源位置
=>[“(内部评级)”,8]
好的,那么同一类的两个对象有相同的方法。我想知道这是否总是真的
> obj1.instance_eval do
> def some_method
> puts 'what is going on here?'
> end
> end
=> nil
> obj1.some_method
what is going on here?
=> nil
> obj2.some_method
Inside Child
=> nil
> obj1.method(:some_method)
=> #<Method: #<Child:0x2b9c128>.some_method>
> obj1.method(:some_method).source_location
=> ["(irb)", 19]
>obj1.instance\u eval do
>定义某些方法
>“这里发生了什么事?”
>结束
>结束
=>零
>obj1.u方法
这是怎么回事?
=>零
>obj2.u方法
内童
=>零
>obj1.方法(:某些方法)
=> #
>obj1.方法(:某些方法)。源位置
=>[“(内部评级)”,19]
那很有趣
詹姆斯·科格兰(James Coglan)有一篇很好的博客文章,对其中的许多问题都给出了比我现在更好的解释
当考虑这一点的时候,也可能是有趣的。想想这个系统有多少是解释器的一个实现细节,在MRI、JRuby和Rubinius中可以进行不同的处理,以及Ruby程序要在所有这些系统中一致地执行到底需要什么一致性。更多值得思考的东西
> obj1.instance_eval do
> def some_method
> puts "Inside Instance"
> super
> end
> end
=> :some_method
Inside Instance
Inside Child
obj1
和obj2
是否各自拥有some\u方法的副本?或者它与JavaScript类似,在JavaScript中,两个对象都可以通过另一个对象(在本例中,通过子类)访问some_方法
BasicObject
尽管我在上面写了些什么,但这是一个合理的假设,事实上,它是如何实现的
ruby -e 'p ObjectSpace.each_object(String).count'
# => 10013
struct Object
object_id: Id
ivars: Dictionary<Symbol, *Object>
class: *Class
end
struct Module
methods: Dictionary<Symbol, *Method>
constants: Dictionary<Symbol, *Object>
cvars: Dictionary<Symbol, *Object>
end
struct Class
methods: Dictionary<Symbol, *Method>
constants: Dictionary<Symbol, *Object>
cvars: Dictionary<Symbol, *Object>
superclass: *Class
end
struct Object
object_id: Id
ivars: Dictionary<Symbol, *Object>
class: *Class
singleton_class: Class
end
struct Module
methods: Dictionary<Symbol, *Method>
constants: Dictionary<Symbol, *Object>
cvars: Dictionary<Symbol, *Object>
mixins: List<*Module>
end
struct Class
methods: Dictionary<Symbol, *Method>
constants: Dictionary<Symbol, *Object>
cvars: Dictionary<Symbol, *Object>
superclass: *Class
mixins: List<*Module>
end
struct Object
object_id: Id
ivars: Dictionary<Symbol, *Object>
class: *Class
singleton_class: Class
end
struct Class
methods: *Dictionary<Symbol, *Method>
constants: *Dictionary<Symbol, *Object>
cvars: *Dictionary<Symbol, *Object>
superclass: *Class
visible?: Bool
end
M′ = Class.new(
methods = M->methods
constants = M->constants
cvars = M->cvars
superclass = C->superclass
visible? = false
)
C->superclass = *M'
def lookup(meth, obj)
c = obj->class
until res = c->methods[meth]
c = c->superclass
raise MethodNotFound, meth if c.nil?
end
res
end