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:
A::Base
class?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_name
defined on the same object at the same time. BUT, you could do something like this:
module MacroMethods
private
def full_name(full_name)
# non-trivial, one-time-only set-up code exists here in actual usage
# this method can only be called once in the definition of any given class,
# because after the first call, it will be redefined!
extend AccessorMethods
end
end
module AccessorMethods
public
def full_name
# a non-trivial, runtime-calculated value is returned here in actual usage
end
end
class Base
extend MacroMethods
end
class Something < Base
full_name 'after this call, I will get a new full_name method!'
end
class SomethingElse < Base
full_name 'so will I!'
end