Inspect, looking in from the outside

T

Trans

Hi--

I've been hadling a lot of OpenStruct like classes the last few days.
It isn;t alwasy smooth sailing. I've been thinking about accessing
certain "metainfo" about an object from the outside rather then from
the inside to ensure certain results. A friend say it goes against the
grain of OOP and polymorphism, but I wonder if certian "metainfo"
shouldn't? What do others think?

Also have a look at my example code below.

Thanks,
T.


---

# The Inspect module provides a guaranteed means of inspecting
# an object and seeing it for what it really is. Using a
# separate module prevents the methods from being overridden
# in the class/object being inspected. For example using the
# Inspect module methods, a Proxy object will be seen as a
# Proxy object and not it's delegate.

module Inspect
extend self

OBJECT_INSPECTION_METHODS = [
:send, :dup, :clone, :eek:bject_id,
:class, :is_a?, :kind_of?,
:respond_to?, :method, :methods,
:instance_variable_get, :instance_variable_set,
:instance_eval
]

CLASS_INSPECTION_METHODS = [
:instance_methods, :class_eval, :module_eval, :method_defined?
]

def define_inspection_method( name, old_name=name, from=Object )
if from.method_defined?( old_name )
im = from.instance_method( old_name )
define_method(name) do |slf,*args|
im.bind(slf).call(*args)
end
end
end

define_inspection_method( :id, :eek:bject_id )
define_inspection_method( :var_get, :instance_variable_get )
define_inspection_method( :var_set, :instance_variable_set )

OBJECT_INSPECTION_METHODS.each do |m|
define_inspection_method( m )
end

define_inspection_method( :class_of?, :===, Class )

CLASS_INSPECTION_METHODS.each do |m|
define_inspection_method( m, m, Class )
end

def nil?(obj) ; is_a?(obj, NilClass) ; end
def false?(obj) ; is_a?(obj, FalseClass) ; end
def true?(obj) ; is_a?(obj, TrueClass) ; end
def bool?(obj) ; is_a?(obj, FalseClass) or is_a?(obj, TrueClass) ;
end

def null?( obj )
defined?(NullClass) and is_a?(slf,NullClass)
end

def nack?( obj )
defined?(NackClass) and is_a?(slf,NackClass)
end

def f?( obj )
return true if is_a?(obj,NilClass)
return true if defined?(NullClass) and is_a?(obj,NullClass)
return true if defined?(NackClass) and is_a?(obj,NackClass)
false
end

def t?( obj )
return false if is_a?(obj,NilClass)
return false if defined?(NullClass) and is_a?(obj,NullClass)
return false if defined?(NackClass) and is_a?(obj,NackClass)
true
end

end

class Object
def instance
@_instance ||= Functor.new { |op, *args| Inspect.__send__(op, self,
*args) }
end
end
 
F

Florian Groß

Trans said:
I've been thinking about accessing
certain "metainfo" about an object from the outside rather then from
the inside to ensure certain results. A friend say it goes against the
grain of OOP and polymorphism, but I wonder if certian "metainfo"
shouldn't? What do others think?

I dunno, I've been fine with Object.instance_method:)inspect).bind(obj)
so far -- sure, you can wrap it in a module for convenience, but is it
really done that frequently?
 
T

Trans

Florian said:
I dunno, I've been fine with Object.instance_method:)inspect).bind(obj)
so far -- sure, you can wrap it in a module for convenience, but is it
really done that frequently?

Ah! You are right. Though writing this out is way too long if you do
use it more then a few times --which I am. Nonetheless I've worked out
another way of dealing with it which wraps it up nicely, so it's no
bother.

require 'mega/blankslate'

class Object

class Inspector < BlankSlate
def initialize( obj )
@obj = obj
end
def method_missing( sym, *args, &blk )
Object.instance_method( sym ).bind(@obj).call(*args, &blk )
end
end

def instance
@_inspector ||= Inspector.new(self)
end

end

It would be nice if there could be a module/class method version, as
this still resides in the instance method namespace, but such is not as
strightfoward. Anyway one point of entry in the instance space is
manageable, I guess.

Any additional suggestions? :)

Thanks!
T.
 
T

Trans

I've refined the module idea. I moved the methods to ObjectSpace
instead. So:

class C
def object_id ; "Argh!" ; end
end

c = C.new
c.object_id #=> "Argh!"

Yes, we've been thwarted, but OpectSpace to the rescue!

ObjectSpace.object_id(c) #=> -606603492

There are some shortcuts too like:

ObjectSpace.id(c) #=> -606603492

One might wonder about the methods that are being overridden in
ObjectSpace itself. Well, despite their very rare potential usage,
that's the whole problem this intends to solve. So,

ObjectSpace.object_id(ObjectSpace) #=> -605307980

So what do other's think? Is this better then depending on __id__ and a
gaagle of other __xyz__ methods, or no?

T.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,151
Latest member
JaclynMarl
Top