How to get class of BasicObject ancestor (Ruby 1.9.2)?

There's no :class method on BasicObject, is there any way to get class
of it's ancestors?

class SomeUtilityClassBase < BasicObject
  def clone
    clone = self.class.new # <= problem here, there's no way to get
:class
    ...
    return clone
  end
end

class Config < SomeUtilityClassBase
end

a = Config.new
b = a.clone

Thanks.

···

--
Posted via http://www.ruby-forum.com/.

Here's one way:

module DefineClass
  def self.included(other)
    other.class_eval {
      define_method :class do
        other
      end
    }
  end
end

class SO < BasicObject
  include ::DefineClass

  @@counter = 0
  def initialize(*a, &b)
    super
    @@counter += 1
  end

  def clone
    clone = self.class.new
  end

  def inspect
    "<#{self.class}: #{@@counter}>"
  end
end

s = SO.new
p s.clone

# => <SO: 2>

(I'm not a huge fan of @@class_variables in general - it's just here
to make the point that there are two different instances.)

Regards,
Sean

···

On Sun, Mar 6, 2011 at 3:09 PM, Alexey Petrushin <axyd80@gmail.com> wrote:

There's no :class method on BasicObject, is there any way to get class
of it's ancestors?

You can inherit from BlankSlate instead of BasicObject, which was
modeled after BlankSlate, and call YourClassName.reveal(:class) to
enable the class method.

···

--
Posted via http://www.ruby-forum.com/.

...or even simpler: just open up BasicObject and monkeypatch a class
method called class(untested):

class BasicObject
  def self.class
    self
  end
end

Then have at it.

···

--
Posted via http://www.ruby-forum.com/.

Thanks for advices, good news for me is that I have small amount of
ancestors, so for now I just hardcoded it's class names.

In my case using :inherited callback magic is too over engineered
solution :slight_smile:

···

--
Posted via http://www.ruby-forum.com/.

7stud -- wrote in post #985807:

If you inherit from BlankSlate instead of BasicObject. The advantage
of doing that is that BlankSlate has a class method called reveal(),
which you can use to incrementally roll back your BlankSlate. In your
case, you would call YourClassName.reveal(:class) to
enable the class method.

That last line should be:

"enable the :class instance method"

and the first line should read:

"You can inherit from BlankSlate instead of BasicObject."

···

--
Posted via http://www.ruby-forum.com/\.

BasicObject as a singleton already has the class method (and it returns Class, as expected).
You meant to suggest something like this:

class BasicObject
  def class
    BasicObject
  end
end

But that would make any subclass of BasicObject that doesn't override this #class definition
would return BasicObject, which would be odd. I'm not sure of a pure-ruby way to write #class,
it's definitely written in C for the Object class.

Michael Edgar
adgar@carboni.ca
http://carboni.ca/

···

On Mar 6, 2011, at 4:21 PM, 7stud -- wrote:

...or even simpler: just open up BasicObject and monkeypatch a class
method called class(untested):

class BasicObject
def self.class
   self
end
end

Then have at it.

--
Posted via http://www.ruby-forum.com/\.

...or even simpler: just open up BasicObject and monkeypatch a class
method called class(untested):

!

class BasicObject
def self.class
self
end
end

Then have at it.

You've changed the #class method of the BasicObject /class/, not the /instance/.
So BasicObject.class will now return BasicObject (rather than Class)
and BasicObject.new.class will not work.

Regards,
Sean

···

On Sun, Mar 6, 2011 at 9:21 PM, 7stud -- <bbxx789_05ss@yahoo.com> wrote:

I'm not sure of a pure-ruby way to write #class,
it's definitely written in C for the Object class.

Here's another attempt (this time handling inheritance):

module DefineClass
  def self.define_class(klass)
    klass.class_eval {
      define_method :class do
        klass
      end
    }
  end
  def self.extended(other)
    define_class(other)
  end
  def inherited(other)
    DefineClass.define_class(other)
  end
end

class SO < BasicObject
  extend ::DefineClass

  @@counter = 0
  def initialize(*a, &b)
    super
    @@counter += 1
  end

  def clone
    clone = self.class.new
  end

  def inspect
    "<#{self.class}: #{@@counter}>"
  end
end

s = SO.new
p s.clone
# => <SO: 2>

class BO < SO
end

b = BO.new
p b.clone
# => <BO: 4>

Regards,
Sean