Adam Shelly
2/21/2006 6:23:00 PM
On 2/19/06, Adam Shelly <adam.shelly@gmail.com> wrote:
> The only part I don't really like is the a_init_
> sentinel I had to add to pass Koan9.
Ok, after looking at some of the other solutions, I've refined my solution.
It now handles multiple attributes with initializers.
I think I disagree with Ara about what to do when provided with both a
block and a hash. With multiple attributes, it makes more sense to me
if the block acts as a default, rather than an override, so that you
get the following:
t = Class.new {attribute(:a,:b=>4,:c=>2){10*b+c} }.new
[t.a, t.b, t.c] => [42, 4, 2]
To get Ara's preferred behaviour, just add `,&block` before the `and`
on the 4th line.
I notice that most people extended Module, while I extended Object.
Is there a reason to prefer one over the other?
-Adam
#-------Knowledge.rb
#
class Object
def attribute *names, &block
names.each do |name|
attribute *name.map{|k,v|[k,v]} and next if name.kind_of? Hash
name,v = name
class_eval "def #{name};"+
"@#{name}=(defined?(@#{name}) ? @#{name} : #{name}_init_); end"
class_eval "def #{name}?; !(self.#{name}.nil?); end"
class_eval "def #{name}=(v); @#{name}=v; end"
private; define_method("#{name}_init_", block || proc {v})
end
end
end