Ivan
Ivan

Reputation: 104089

Creating a new non-singleton class based on a singleton class

Is it possible in Ruby to define a new non-singleton class based on a singleton class?

I tried something like this (snip):

module SomeModule
  extend self
  class Singleton;end
end

class NonSingleton
  include SomeModule
end
nonsingleton = NonSingleton.new

But of course to you gurus it's already evident that this won't work as I expected.

Basically what I want is to re-use the functionality of the Singleton class, without affecting it's behavior in any way. Is it possible?

After further investigation, it would seem that this ain't possible at all (please correct me if I'm wrong). Would a hack like following be too fugly/messy?

singleton = File.read('some_singleton.rb')
non_singleton = eval(singleton.gsub('include Singleton', ''))
# Or perhaps:
non_singleton = eval(singleton.gsub('module SomeModule', 'module MyOwnModule'))

Upvotes: 0

Views: 556

Answers (1)

Orion Edwards
Orion Edwards

Reputation: 123662

OK. I don't have real ruby here, only IronRuby, but this is what happens when I try to do it:

# define a new object
>>> s = "hello"
=> "hello"

# add a method to it's singleton class
>>> class << s
... def say; puts self; end
... end
=> nil

# get it's singleton class
>>> SingletonBaseClass = class << s; self; end
=> #<Class:#<String:0x000005c>>

# try build a new one inheriting from the singleton class
>>> class NonSingletonClass < SingletonBaseClass
... end
:0: can't make subclass of virtual class (TypeError)

IronRuby is fairly compliant with the normal ruby language itself, I'd be willing to bet that a similar error message would happen in real ruby. In short, you can't do it.

This begs the question: what are you trying to do? If a singleton class for a particular object is getting complicated enough that you want to re-use it, shouldn't you just be putting that code in a regular class or module?

For example, you could do this:

# define our reusable code
module SharedMethods
  def a;end
  def b;end
  # and so on
end

# mix it into the singleton of some object
s = "hello"
class << s; include SharedMethods; end

You could then re-use it on any other object/class/etc

Upvotes: 1

Related Questions