Alex Velickiy
Alex Velickiy

Reputation: 571

Ruby: mixins, inheritance and constants name resolution

My program has following structure:

module M1
    class A
        def action
            C.new.foo
        end
    end

    class C
        def foo
            puts "M1::C foo"
        end
    end
end


module M2
    class A
        def action
            C.new.foo
        end
    end

    class C
        def foo
            puts "M2::C foo"
        end
    end
end

As both M1::A and M2::A share same code, I've been thinking of putting common code inside separate class (or module) and inherit from it (include it). Something like this:

class ABase
    def action
        C.new.foo
    end
end

module M1
    class A < ABase
    end

    class C
        def foo
            puts "M1::C foo"
        end
    end
end


module M2
    class A < ABase
    end

    class C
        def foo
            puts "M2::C foo"
        end
    end
end

However, when I tried, I've got into trouble with name resolution uninitialized constant ABase::C. What is the proper way to achieve code sharing in this case?

Upvotes: 2

Views: 106

Answers (1)

tadman
tadman

Reputation: 211610

Due to the way constants are resolved based on definition scope and not in inherited scopes you'll need to bridge that with a method call:

class ABase
  def action
    # Within this scope only constants defined in `ABase` are resolved.
    # As ABase::C and ::C (root-level) don't exist, C can't be resolved.
    # However, a method `c` defined in a subclass will be.
    c.new.foo
  end
end

module M1
  class A < ABase
    def c
      C
    end
  end

  class C
    def foo
      puts "M1::C foo"
    end
  end
end

module M2
  class A < ABase
    # This resolves C as either M2::A::C, M2::ABase::C, M2::C or ::C,
    # whichever it finds first.
    def c
      C
    end
  end

  class C
    def foo
      puts "M2::C foo"
    end
  end
end

Then you get the expected results:

M1::A.new.action
# => M1::C foo
M2::A.new.action
# => M2::C foo

Upvotes: 1

Related Questions