Ruby 在类和它的某个祖先之间定义的实例方法
假设类Ruby 在类和它的某个祖先之间定义的实例方法,ruby,inheritance,subclass,Ruby,Inheritance,Subclass,假设类A是类B的后代。获取B中定义的A的所有实例方法(即B或其任何子类中定义的A的实例方法)列表(符号数组,顺序不重要)的最佳方法是什么?示例如下。其中,类层次结构如下所示: class C; def c; end end class B < C; def b; end end class D < B; def d; end end class A < D; def a; end end 我相信你正在寻找这个: class Class def instance_metho
A
是类B
的后代。获取B
中定义的A
的所有实例方法(即B
或其任何子类中定义的A
的实例方法)列表(符号数组,顺序不重要)的最佳方法是什么?示例如下。其中,类层次结构如下所示:
class C; def c; end end
class B < C; def b; end end
class D < B; def d; end end
class A < D; def a; end end
我相信你正在寻找这个:
class Class
def instance_methods_within(klass)
return self.instance_methods if klass == Object
methods = []
this = self
while this != nil
methods << this.instance_methods(false)
break if this == klass
this = this.superclass
end
return methods.flatten
end
end
class C; def c; end end
class B < C; def b; end end
class D < B; def d; end end
class A < D; def a; end end
A.instance_methods_within(Object) # => (Same as A.instance_methods)
A.instance_methods_within(C) # => [:a, :d, :b, :c]
A.instance_methods_within(B) # => [:a, :d, :b]
A.instance_methods_within(D) # => [:a, :d]
A.instance_methods_within(A) # => [:a] (Same as A.instance_methods(false))
类
def实例中的方法(klass)
如果klass==Object,则返回self.instance_方法
方法=[]
这个=自我
而这个无
方法(与A.instance_方法相同)
A.instance_methods_在(C)#=>[:A,:d,:b,:C]
A.实例_方法_在(B)#=>[:A,:d,:B]
A.instance_methods_在(D)#=>[:A,:D]
A.instance_methods_在(A)#=>[:A](与A.instance_methods(false)相同)
我将
对象
的特例添加为对象。实例方法(false)
产生[]
,因此在这种情况下向上遍历循环将无法正常工作。更新后将类中的实例方法定义为类的实例方法这是我自己的解决方案
class Class
def instance_methods_within klass
ancestors
.select{|k| k <= klass}
.inject([]){|a, k| a.concat(k.instance_methods(false))}
.uniq
end
end
类
klass中的def实例方法
祖先
.选择{| k | k我想介绍一下:--
A.instance_方法-C.instance_methods@AlokAnand这是错误的。花点时间。我的答案很快就会发布。@sawa我正在尝试,…。:-)我知道你知道答案。:)是的,这与我的想法很接近。关于对象
的观点很好。如果你不是在A
上定义它,而是作为的一个实例方法,那就更好了类
Class.@sawa在Class
类中作为实例方法放置确实更好,我会编辑我的答案来做这件事。顺便问一下,你知道为什么Object.instance\u方法(false)
产生[]
?有些方法是在内核上定义的,因此它们不应该出现,但是应该在对象上定义方法,显然所有这些方法都是在内核中定义的。根据对象Ruby Doc:Object在内核模块中混合,使得内置内核函数可以全局访问对象的方法是由内核模块定义的,为了清晰起见,我们选择在这里记录它们。我最终使用了我自己的答案,但是感谢关于对象
/内核
的观点。是否需要.uniq
实例方法(false)
不包括超类方法,因此现在什么时候使用uniq
呢?如果A
有foo
而B
有foo
,那么只有A
的foo
应该被计算在内。@Marc AndréLafortune谢谢,我没有意识到这一点。很好,@sawa我看不出这有什么可以改进的地方(尽管我承认我不理解对平面地图的间接引用)。请注意,take_,而
可以用来代替select
。我比较喜欢这种阅读方式。您可能注意到我发布了一个错误的解决方案,后来被删除了。我认为可以用实例方法
,实例方法(false)来完成
,并在数组上设置类型操作。在@Alok指出了一个问题(并提请注意我缺乏测试)之后,我又尝试了一次,但最终得出结论认为这是一条死胡同。当a
有foo
和B
有foo
时,您的答案返回[]
@sawa将在一段时间内进行修改,前往Holi节日庆典。@sawa我已经修改了代码,请进行审阅。我想它现在不会抛出错误的数组。
class Class
def instance_methods_within klass
ancestors
.select{|k| k <= klass}
.inject([]){|a, k| a.concat(k.instance_methods(false))}
.uniq
end
end
class Class
def instance_methods_within klass
ancestors
.select{|k| k <= klass}
.flat_map{|k| k.instance_methods(false)}
.uniq
end
end
class Class
def instance_methods_within(klass = nil)
imethods = instance_methods
own_imethods = instance_methods(false)
return imethods if [Object, Kernel, nil].include?(klass) || [BasicObject, nil].include?(klass.superclass)
sc_imethods = klass.superclass.instance_methods
own_imethods | (imethods - sc_imethods)
end
end