Subclass a class in the namespace of the that subclass

Ever get stuck on a problem, and then after staring at it for way too
long, get disgusted b/c there is no way to do it the way you need to
do it, and none of the workable alternatives quite cut it? Well,
that's been my day.

I know it may seem a bit off the wall. But I want to subclass a class
that is also defined in the namespace of the subclass. In other words:

  class X < Y
    class Y
    end
  end

Why do I want to do this? Because my library (X) consists of a few
components, one of them being Y. And I want the end user of the
library to use it by typing "X.new". Now, X is all but the same as Y,
with only with some minor adjustments.

Unfortunately for me there seems to be no way to do this without Ruby
complaining of a superclass mismatch.

In the end my alternatives appear to be:

1) Use Z instead of X and fake it with X:

  module X
    def self.new
      Z.new
    end
    class Z < Y
    end
  end

2) Delegate Y in X

  class X
    def initialize
      @y = Y.new
    end
    def method_missing ...
  end

#1 sucks because I'm faking it --X isn't really new. And #2 sucks
because it is nothing but a class wrapped around a single instance
variable --a complete waste of resources.

I imagine there is a tricky dynamic coding way to do it, but that will
screw up my RDocs.

Well, I don't see any solution for it --if you have one I'll be
amazed. But at least I got to vent.

T.

Tom, that's easy if you split the creation of the classes from naming them:

  y = Class.new

  class X < y
  end

  X::Y = y

  p X.ancestors # => [X, X::Y, Object, Kernel]

Regards,
Pit

···

2008/10/22 Trans <transfire@gmail.com>:

I know it may seem a bit off the wall. But I want to subclass a class
that is also defined in the namespace of the subclass. In other words:

class X < Y
   class Y
   end
end

Hi --

Ever get stuck on a problem, and then after staring at it for way too
long, get disgusted b/c there is no way to do it the way you need to
do it, and none of the workable alternatives quite cut it? Well,
that's been my day.

I know it may seem a bit off the wall. But I want to subclass a class
that is also defined in the namespace of the subclass. In other words:

class X < Y
   class Y
   end
end

Why do I want to do this? Because my library (X) consists of a few
components, one of them being Y. And I want the end user of the
library to use it by typing "X.new". Now, X is all but the same as Y,
with only with some minor adjustments.

Unfortunately for me there seems to be no way to do this without Ruby
complaining of a superclass mismatch.

How about this?

c = Class.new
X = Class.new(c)
X.class_eval do
   const_set("Y",c)
end

p X::Y # X::Y
p X.superclass # X::Y
p X.superclass == X::Y # true

(I used const_set instead of Y = c because that created a top-level
constant.)

I don't know what you need it for but if that helps, there it is :slight_smile:

David

···

On Thu, 23 Oct 2008, Trans wrote:

--
Rails training from David A. Black and Ruby Power and Light:
   Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
   Advancing with Rails January 19-22 Fort Lauderdale, FL *
   * Co-taught with Patrick Ewing!
See http://www.rubypal.com for details and updates!

class X < Y
   class Y
   end
end

Could you make Y a module?

class X
  module Y
    # methods
  end
  include Y
  # more methods
end

Or, if Y needs to be a class:

class X
  module M
    # methods for Y
  end
  class Y; include M; end # Y implements nothing itself
  include M
  # add methods to X here
end

That way, X and Y both inherit from M, but Y is basically an empty class
that acts as an instantiable version of module M.

···

--
James Coglan
http://blog.jcoglan.com

invert:

cfp:~ > cat a.rb
class Y
   def Y.foo() 42 end

   class ::X < Y
     Y = Y
   end
end

p(Y == X::Y)

p X.foo

cfp:~ > ruby a.rb
true
42

a @ http://codeforpeople.com/

···

On Oct 22, 2008, at 3:53 PM, Trans wrote:

I know it may seem a bit off the wall. But I want to subclass a class
that is also defined in the namespace of the subclass. In other words:

class X < Y
   class Y
   end
end

Why do I want to do this? Because my library (X) consists of a few
components, one of them being Y. And I want the end user of the
library to use it by typing "X.new". Now, X is all but the same as Y,
with only with some minor adjustments.

Unfortunately for me there seems to be no way to do this without Ruby
complaining of a superclass mismatch.

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

Aren't you introducing a circular dependency here? I'd try to avoid
that. These things cause all sorts of bad effects (e.g. headache for
me). Even if it is possible if feels most awkward to me.

Kind regards

robert

···

2008/10/22 Trans <transfire@gmail.com>:

Ever get stuck on a problem, and then after staring at it for way too
long, get disgusted b/c there is no way to do it the way you need to
do it, and none of the workable alternatives quite cut it? Well,
that's been my day.

I know it may seem a bit off the wall. But I want to subclass a class
that is also defined in the namespace of the subclass. In other words:

class X < Y
   class Y
   end
end

--
remember.guy do |as, often| as.you_can - without end

Thanks Pit (and David),

The solution is cleaner than I thought it would be actually --that's
good, but I avoided this direction myself b/c of how it would effect
RDocs. RDoc sees X::Y as just a constant and not a class. Yea, I know
I shouldn't code to the rdocs, but unfortunately RDocs are important.
Maybe something to consider for improving Rdocs in the future, a way
to force it to recognize certain dynamic designs as particular
constructs. But I digress...

Another option that occurred to me, I could make X the primary class
and subclass it as Y even though it would mean a couple
remove_methods. Still not ideal but perhaps close enough.

T.

···

On Oct 22, 6:08 pm, "Pit Capitain" <pit.capit...@gmail.com> wrote:

Tom, that's easy if you split the creation of the classes from naming them:

y = Class.new

class X < y
end

X::Y = y

p X.ancestors # => [X, X::Y, Object, Kernel]

Hi --

> Ever get stuck on a problem, and then after staring at it for way too
> long, get disgusted b/c there is no way to do it the way you need to
> do it, and none of the workable alternatives quite cut it? Well,
> that's been my day.

> I know it may seem a bit off the wall. But I want to subclass a class
> that is also defined in the namespace of the subclass. In other words:

> class X < Y
> class Y
> end
> end

> Why do I want to do this? Because my library (X) consists of a few
> components, one of them being Y. And I want the end user of the
> library to use it by typing "X.new". Now, X is all but the same as Y,
> with only with some minor adjustments.

> Unfortunately for me there seems to be no way to do this without Ruby
> complaining of a superclass mismatch.

How about this?

c = Class.new
X = Class.new(c)
X.class_eval do
const_set("Y",c)
end

p X::Y # X::Y
p X.superclass # X::Y
p X.superclass == X::Y # true

(I used const_set instead of Y = c because that created a top-level
constant.)

(see my response to the Captain)

I don't know what you need it for but if that helps, there it is :slight_smile:

Ok. Well I'll spill... I've been working on an "uber" commandline
parser:

  class Usage < Command
    class Command
    class Option
    class Argument

Thus Usage is the main toplevel command. A command can have
subcommands, options, arguments... so forth and so on.

T.

···

On Oct 22, 6:09 pm, "David A. Black" <dbl...@rubypal.com> wrote:

On Thu, 23 Oct 2008, Trans wrote:

That's probably the most justifiable approach under the circumstances
(though lately I've been shying away a bit from modules[1]), most any
other time I'd likely do that. But in this case, it just doesn't seem
to fit. I have to name this module something (what?) and then I'll
have to explain why it even exists, in the docs, and so on --it feels
too "bolted on".

I'll just have to think on it more.

Thanks,
T.

[1] Yes, Austin I've learned a thing or two from you. :slight_smile:

···

On Oct 22, 6:30 pm, "James Coglan" <jcog...@googlemail.com> wrote:

> class X < Y
> class Y
> end
> end

Could you make Y a module?

class X
module Y
# methods
end
include Y
# more methods
end

Or, if Y needs to be a class:

class X
module M
# methods for Y
end
class Y; include M; end # Y implements nothing itself
include M
# add methods to X here
end

That way, X and Y both inherit from M, but Y is basically an empty class
that acts as an instantiable version of module M.

Hi --

···

On Thu, 23 Oct 2008, Trans wrote:

On Oct 22, 6:08 pm, "Pit Capitain" <pit.capit...@gmail.com> wrote:

Tom, that's easy if you split the creation of the classes from naming them:

y = Class.new

class X < y
end

X::Y = y

p X.ancestors # => [X, X::Y, Object, Kernel]

Thanks Pit (and David),

The solution is cleaner than I thought it would be actually --that's
good, but I avoided this direction myself b/c of how it would effect
RDocs. RDoc sees X::Y as just a constant and not a class. Yea, I know
I shouldn't code to the rdocs, but unfortunately RDocs are important.
Maybe something to consider for improving Rdocs in the future, a way
to force it to recognize certain dynamic designs as particular
constructs. But I digress...

I really wouldn't worry about RDoc in this context. Ruby is always
going to be too dynamic and elastic for all of it to be captured by
pre-processing for documentation (and the dangers of executing code in
order to document it are too great).

David

--
Rails training from David A. Black and Ruby Power and Light:
   Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
   Advancing with Rails January 19-22 Fort Lauderdale, FL *
   * Co-taught with Patrick Ewing!
See http://www.rubypal.com for details and updates!