やってみたらできました(Ruby 2.6.3)。業務では使う意味がないというか使わないでください。
class Foo
def initialize
@a = 1
@b = 2
end
def inspect
puts @a
puts @b
end
end
簡単のため、上のinitialize
には引数もブロックも渡していません。
以下は普通にnew
した場合です。
» a = Foo.new
1
2
» a.inspect
1
2
allocate
とtap
とsend
でやる
Class#allocate
を使うと、initialize
を呼び出さずにインスタンスを生成できるinitialize
メソッドはprivateなので、send(:initialize)
で無理やり呼び出すtap
を使ってsend(:initialize)
のブロックをねじ込む
» a = Foo.allocate.tap {|i| i.send(:initialize) }
1
2
#»
» a.class
#» Foo
» a.inspect
1
2
参考: instance method Class#allocate
(Ruby 2.6.0)
参考: instance method Object#tap
(Ruby 2.6.0)
参考: instance method Object#__send__
(Ruby 2.6.0)
Rubyのinitialize
メソッドは特殊
Rubyのinitialize
メソッドは、普通のインスタンスメソッドのような形をしていながら、例外的にprivateメソッドにされます。
» Foo.initialize
NoMethodError: private method `initialize' called for Foo:Class
from (pry):14:in `__pry__'
参考: instance method Object\#initialize
(Ruby 2.6.0)
initialize という名前のメソッドは自動的に private に設定されます。
docs.ruby-lang.orgより
おたより発掘
Ruby: `new`を使わずにクラスのinitializeを実行してみる
Foo.allocate.instance_eval { initialize } と言う手もありますな
ありがとうございます!pryではうまく動かなかったのですが、ファイルにしたら動きました。
ファイルの場合
# not_new.rb
#!/usr/bin/env ruby -
# encoding: UTF-8
class Foo
def initialize
@a = 1
@b = 2
end
def inspect
puts @a
puts @b
end
end
p a = Foo.new
p a.inspect
$ ruby not_new.rb
1
2
1
2
(参考)pryの場合
» class Foo
» def initialize
» @a = 1
» @b = 2
» end
»
» def inspect
» puts @a
» puts @b
» end
» end
#» :inspect
» foo = Foo.allocate.instance_eval { initialize }
#» 2
» foo.inspect
#» "2"