Фактически, этот вид подразумевает, что есть лучший способ, так как интерпретатор Ruby явно знает лучше, чем доверять a.class. Но я не уверен, как получить доступ к этим знаниям.
ил с метапрограммированием в Ruby, и я сделал этот код:
class Class
def ===(other)
other.kind_of?(self)
end
end
class FakeClass
def initialize(object)
methods.each {|m| eval "undef #{m}" if m.to_sym != :methods }
define = proc do |m|
eval(<<-END)
def #{m}(*a, &b)
@object.#{m}(*a, &b)
rescue Object
raise $!.class, $!.message.gsub("FakeClass", @object.class.to_s),
$!.backtrace-[$!.backtrace[-caller.size-1]]
end
END
end
object.methods.each {|m| define[m] }
def method_missing(name, *a, &b)
if @object.methods.include?(name.to_s)
define[name]
eval "@object.#{name}(*a, &b)"
elsif @object.methods.include?("method_missing")
eval "@object.#{name}(*a, &b)"
else
super
end
rescue Object
raise $!.class, $!.message.gsub("FakeClass", @object.class.to_s),
$!.backtrace-[$!.backtrace[-caller.size-1]]
end
@object = object
end
end
Это создает поддельный класс, который имитирует объект. Смотреть:
a = FakeClass.new(1) # => 1
a.class # => Fixnum
a.methods # => Return all Fixnum methods
a + 1 # => 2 (is not a FakeClass)
Fixnum === a # => true
a.something # => NoMethodError:
# undefined method `something' for 1:Fixnum
class Fixnum
def foo
true
end
end
a.foo # => true
Проблема в том, что теперь я не знаю, как узнать, является ли объект реальным или поддельным. Другими словами, если#class
возвращает истинный класс объекта. Есть какой-то чистый рубиновый способ дифференциации?
Подумайте о сценарии, в котором я не знаю, существует ли FakeClass или я не знаю, как называется FakeClass. Это означает, что я не могу редактировать FakeClass, чтобы добавить метод, подобный#is_fake?
.
PS: я знаю этоa.instance_eval {self}
возвращает объект (не подделка). Но это не помогает проверить, еслиa
это подделка.