Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 在类和它的某个祖先之间定义的实例方法_Ruby_Inheritance_Subclass - Fatal编程技术网

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