I have a class that was built for subclassing.
class A
def initialize(name)
end
def some
# to define in subclass
end
end
# usage
p A.new('foo').some
#=> nil
In my use case, I don't want to create a subclass since I need just one instance. Therefore, I'll change the initialize
method to support the following usage.
p A.new('foo') { 'YEAH' }.some
#=> YEAH
How could I support the usage above?
BTW: I found the following solutions for a Ruby 1.8.7 project, but they look awkward to me.
class A
def singleton_class
class << self; self; end
end
def initialize(name, &block)
@name = name
self.singleton_class.send(:define_method, :some) { block.call } if block_given?
end
def some
# to define in subclass
end
end
You can store the block argument in an instance variable and call
it later on:
class A
def initialize(name, &block)
@name = name
@block = block
end
def some
@block.call
end
end
A.new('foo') { 'YEAH' }.some
#=> "YEAH"
You can also pass arguments into the block:
class A
# ...
def some
@block.call(@name)
end
end
A.new('foo') { |s| s.upcase }.some
#=> "FOO"
Or instance_exec
the block in the context of the receiver:
class A
# ...
def some
instance_exec(&@block)
end
end
Which allows you to bypass encapsulation:
A.new('foo') { @name.upcase }.some
#=> "FOO"