la, 2005-04-30 kello 00:14, Vincent Foley kirjoitti:
> Hi everyone,
> 
> I finished playing yet another game of Chrono Trigger the other day,
> and I thought I would look at how I could implement a simple Character
> system in Ruby.  I have the following initialize method, but I would
> like to be sure it's not extremely bad style:
> 
> class Character
>   attr_accessor :strength, :magic, :defense, :magic_defense
> 
>   def initialize(args = {})
>     args.each do |k, v|
>       instance_variable_set("@#{k}", v) if respond_to?(k)
>     end
> 
>     methods.grep(/\w=$/).each { |setter|
>       getter = setter[0..-2]
>       if send(getter).nil?
>         send(setter, 0)
>       end
>     }
>   end
> end
> 
> So, if I added a :critical_rate accessor, I wouldn't need to modify
> anything else in the initialize method.  Also, I don't want nil in any
> attribute.  Is this good style?  Are there other (maybe better) ways to
> accomplish this?  Thank you.

Hello,
I've been using a pretty similar class for my config needs, maybe the
biggest difference is that I'm using a default_config method to get the
default values and to make it work properly with subclassing.

I quite like the respond_to?-check you've got there, think I'll extend
mine by raising a name error if the setter doesn't exist.. or just use a
config block more often :|

Anyhow, here's the class:

class Configurable

  def initialize(config = {}, &optional_config_block)
    config = default_config.merge(config)
    config.each{|k,v| instance_variable_set("@#{k}", v)}
    optional_config_block.call(self) if block_given?
  end

  def default_config
    {}
  end

end

#subclassing:

class Foo < Configurable
  attr_accessor :foo

  def default_config
    super.merge({
      :foo => 10
    })
  end
end

Foo.new :foo => 5
Foo.new{|f| f.foo = 5 }

class FooBar < Foo
  attr_accessor :bar

  def default_config
    super.merge({
      :bar => 20
    })
  end
end

fb = FooBar.new
fb.foo #=> 10
fb.bar #=> 20