Рубин: is_a?и instance_of?в BasicObject - PullRequest
0 голосов
/ 28 мая 2018

Как работает is_a?и instance_of?методы работают с подклассом BasicObject?

class My < BasicObject
  DELEGATE = [:is_a?, :instance_of?]
  def method_missing(name, *args, &blk)
    superclass unless DELEGATE.include? name
    ::Kernel.send(name,*args, &blk) 
  end
end

my = My.new
my.is_a? BasicObject  #=> true
my.is_a? My           #=> false ???
my.instance_of? My    #=> false ???

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

Вы можете украсть is_a? из Kernel:

class My < BasicObject
  define_method(:is_a?, ::Kernel.method(:is_a?))
end

m = My.new
m.is_a?(My)          #=> true
m.is_a?(BasicObject) #=> true
m.is_a?(Object)      #=> false

Если вы собираетесь построить собственную иерархию объектов, вы также можете определить свою собственную Kernel, что-то вроде:

module MyKernel
  [:is_a?, :instance_of?, :class].each do |m|
    define_method(m, ::Kernel.method(m))
  end
end

class My < BasicObject
  include ::MyKernel
end
0 голосов
/ 28 мая 2018

::Kernel.send(name,*args, &blk) вызывает метод name для класса Kernel с аргументами args и блоком &blk.

При запуске my.is_a? My name равен :is_a?*args равно My, а &blk равно nil.Вы действительно используете Kernel.is_a? My.

Вместо этого, если вы хотите переопределить is_a? для BasicObject, вы можете пройтись по классу ancestors ...

  def is_a?(target)
    # I don't know how to get the current class from an instance
    # that isn't an Object, so I'm hard coding the class instead.
    return ::My.ancestors.include?(target)
  end
...