Combine generic-function with Ruby Object System.
- use nextMethod.call to simulate (call-next-method)
- nextMethod.call == nextMethod.call(arg1, arg2, …)
method = Clos.defGeneric "a_test_method"
method.addMethod [Integer] { |i| "integer"}
method.addMethod [Object] { "object"}
method[1] # or 'method.call(1)' or 'method.(1)'
# => "integer"
method.addMethod [Integer] { |i|
assert_equal nextMethod.call, nextMethod.call(i)
"integer " + nextMethod.call
}
method[233]
# => "integer object"
method[1.5]
# => "object"
result = []
g = Clos.defGeneric "generic-function"
g.addMethod [Integer] {|i| result << i}
g.addMethod :before, [Integer] {result << :start}
g.addMethod :after, [Integer] {result << :end}
g[1] # g.call(1)
result # => [:start, 1, :end]
m1 = Clos.defGeneric "a Name"
m1.addMethod [Integer, String] { :origin }
m1.addMethod :around, [Integer, String] { :new }
m1.(1, "") # => :new
m1.addMethod :around, [Integer, String] {
[:new].push(nextMethod.call)
}
With the native Ruby OO System
# Human -|> Hand
# Human -|> Body
module Hand
attr_accessor :a
end
module Body
attr_accessor :b
end
class Human
include Hand
include Body
attr_accessor :v
end
Clos.init.addMethod [Human] { |h|
h.v = "v"
}
# before init Body
Clos.init.addMethod :before, [Body] { |b|
b.b = "b"
}
# after init Hand
Clos.init.addMethod :after, [Hand] { |h|
h.a = "a"
}
instance = Clos.new(Human)
instance.a # => "a"
instance.b # => "b"
instance.v # => "v"
....