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?
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.