I’m designing/building a system of classes that all derive from a single base class.
The goal is to have easy-to-use inherited macro methods that look something like this:
class Something < A::Base
full_name 'Something that goes bump in the night.'
end
Any code should be able to ask the class for this information (or, likely, normalized/derived infomation) later on via class-level accessor method(s).
puts Something.full_name
# => "Some kind of calculated value that may or may not go bump in the night."
Given that A::Base includes/extends/somehow-otherwise-mixes-in both a module with the macro method that works something like this:
module MacroMethods
private
def full_name(full_name)
# non-trivial, one-time-only set-up code exists here in actual usage
end
end
and a module with the class-level accessor method that works something like this:
module AccessorMethods
public
def full_name
# a non-trivial, runtime-calculated value is returned here in actual usage
end
end
no matter how I mix them in, I’m continually running into naming conflicts (i.e. ‘wrong number of arguments (1 for 0) (ArgumentError)’) between the two.
Note: full_name is the simplest example of what is needed; other, more-complex macros/accessors ensure the non-flexible constraints of macro methods needing to be declared inside the class and needing to be set once-and-only-once.
My question is two-fold:
- Is there a way to make this all work inside of the
A::Baseclass? - Is this the right way to do this in Ruby? Is there a better way go about it, achieving the same result?
Options that have been considered:
-
Calling either the macro or accessor method(s) something else.
(e.g. in Something class:set_up_full_name 'Something that …')
Downside is that the naming is confusing and unconventional. -
Making the accessor method(s) instance-level instead of class-level.
(e.g.puts a_something.full_name')
Downside is that the traits set up by the macros are inherent to the class, not to each instance (in some cases, only a reference to the class may be available, not an instance). -
Creating a single method that handles both macro and accessor functionality.
(e.g. in A::Base class:def self.full_name(*args) …)
Downside is that the macro methods can no longer be private and the RDoc looks like sh*t. -
Using abstact/virtual-ish methods instead.
(e.g. in Something class:def self.full_name; 'Something that …'; end)
Downside is that this is more code in sub-classes and is more of a Objective-C (or C++, or Java, …) thing than a good Ruby paradigm.
Slipp, I read your question carefully. There is no way you can have 2 different methods called
full_namedefined on the same object at the same time. BUT, you could do something like this: