newを書かずにインスタンス生成

newが嫌いな理由 -- リテラル好き好きを読んで、newを書かずにインスタンス生成する実験をRubyでやってみます。

class Person
  def initialize(name)
    @name = name
  end
  def hello
    puts "Hello, #{@name}!"
  end
end

def Person(*args)
  Person.new(*args)
end

# 以上は仕込み。

x = Person('Tonkichi')      # Person.newとしない
x.hello                     #=> Hello, Tonkichi!

うまくいきました♪
ところで、def Personを自動化しようと思い、Class#inheritedの中に埋め込もうと試みたのが次のプログラムです。でもうまくいきませんでした。

class Class
  def inherited(*args)
    eval "
      def #{args}(*a)
        #{args}.new(*a)
      end
    "
  end
end

class Person
  def initialize(name)
    @name = name
  end
  def hello
    puts "Hello, #{@name}!"
  end
end

x = Person('Tonkichi')  #=> undefined method `Person' for main:Object (NoMethodError)
x.hello

次のようにすればうまく行くんですけれどね…。

class Class
  def inherited(*args)
    $func = "
      def #{args}(*a)
        #{args}.new(*a)
      end
    "
  end
end

class Person
  def initialize(name)
    @name = name
  end
  def hello
    puts "Hello, #{@name}!"
  end
end

eval $func

x = Person('Tonkichi')
x.hello                 #=> Hello, Tonkichi!

追記:スーパーな方々からアドバイスが入って、勉強になりまくりです(へんな日本語)。以下、アドバイスを反映したものを順に書きます。
id:sumimさんから、evalの第二引数とTOPLEVEL_BINDINGを教えていただきました。ri evalをやらなかったわたしのミスでしたね。

class Class
  def inherited(*args)
    eval("
      def #{args}(*a)
        #{args}.new(*a)
      end
    ", TOPLEVEL_BINDING)
  end
end

class Person
  def initialize(name)
    @name = name
  end
  def hello
    puts "Hello, #{@name}!"
  end
end

x = Person('Tonkichi')
x.hello                 #=> Hello, Tonkichi!

artonさんからは、module_evalを教えていただきました。

class Class
  def inherited(*args)
    module_eval("
      def #{args}(*a)
        #{args}.new(*a)
      end
    ")
  end
end

class Person
  def initialize(name)
    @name = name
  end
  def hello
    puts "Hello, #{@name}!"
  end
end

x = Person('Tonkichi')
x.hello                 #=> Hello, Tonkichi!

id:iwadonさんから、Kernel.instance_evalを教えていただきました。あらっ? inheritedは引数一つでよいのか…。ここまでのプログラムでわたしはinheritedを*argsで受けていましたね。

class Class
  def inherited(subclass)
    Kernel.instance_eval do
      define_method(subclass.to_s) do |*args|
        subclass.new(*args)
      end
    end
  end
end

class Person
  def initialize(name)
    @name = name
  end
  def hello
    puts "Hello, #{@name}!"
  end
end

x = Person('Tonkichi')
x.hello                 #=> Hello, Tonkichi!

みなさま、ご教示ありがとうございます!
(ツ、ツンデレなんかじゃないんだからねっ!)