Martin DeMello <martindemello / yahoo.com> writes:

> I'm trying to provide an extension to Range that is only valid
> within the context of a few classes

This is not a simple task, but work has been done on it.  See the
following Ruby Behaviors link.

http://uweb.superlink.net/~dblack/ruby/behaviors/
http://www.rubyconf.org/2001/talks/behaviors/example.html

> ; however, wrapping it in a module causes kind_of?  to stop
> identifying ranges as such. Note that this works perfectly if I just
> extend Range inside the file, without using a module. What's the
> difference?
>
>   module ExtendRange
>     class Range

        ^^^^^^^^
This is creating a new ExtendRange::Range class, not modifying the
Range class.

>       def foo
> 	"bar"
>       end
>     end
>   end
>
>   class A
>     def test
>       r = (1..10)
>       [r.kind_of?(Range), r.type == Range, r]

Here, the class name Range names the global Range class.

>     end
>   end
>
>   class B
>     include ExtendRange
>     def test
>       r = (1..10)
>       [r.kind_of?(Range), r.type == Range, r.type]

Here, the class name Range names ExtendedRange::Range, because B
includes ExtendedRange.

>     end
>   end
>
>   a = A.new
>   b = B.new
>   p a.test # => [true, true, Range]
>   p b.test # => [false, false, Range]

See, b.test shows that (1..10) is a Range in both cases, not an
ExtendedRange::Range.


The following modifications to your code show this clearly:

  module ExtendRange
    class Range
      def foo
        "bar"
      end
    end
  end

  class A
    def a_test
      r = (1..10)
      [r.kind_of?(Range),
        r.kind_of?(::Range),
        r.kind_of?(ExtendRange::Range),
        r.respond_to?(:foo)]
    end
  end

  class B < A
    include ExtendRange
    def b_test
      r = (1..10)
      [r.kind_of?(Range),
        r.kind_of?(::Range),
        r.kind_of?(ExtendRange::Range),
        r.respond_to?(:foo)]
    end
  end

  a = A.new
  b = B.new
  p a.a_test # => [true, true, false, false]
  p b.a_test # => [true, true, false, false]
  p b.b_test # => [false, true, false, false]


-- 
matt