On Oct 15, 8:11 am, Yukihiro M. [email protected] wrote:
If I knew traits before designing Ruby, Iād have chosen traits over
modules. But thatās the life.
I have to agree that traits are too much alike and yet too different
from modules to co-exist in the same language. However, I disagree
with this subsequent statement. Much of the benefit of traits can
still be had by overlaying the same concepts on Rubyās modules. In the
end I think the most important part is usability, not so much the
underlying implementation (as long as it is reasonably efficient, of
course). Moreover, I contend that if you are serious when you say, you
would have used traits instead of modules if he had known about them,
then you were fortunate not to have known, b/c modules are a more
powerful composition mechanism, despite their greater implementation
complexity.
To demonstrate my point here is Facetsā module/traits.rb lib. I
improved it a fair bit yesterday --thanks to Robert and this thread.
Iād like others to have a look and provide any feedback. As you will
see in the code, I still have a couple questions about where to use
public vs. all instance methods (which leads me to question/thought
that I will bring up in another thread). Here you goā¦
class Module
# Combine modules.
def +(other)
base = self
Module.new do
include base
include other
end
end
# Subtract modules.
#--
# TODO Should this use all instance_methods, not just public?
#++
def -(other)
case other
when Array
subtract = instance_methods(true) & other.collect{|m| m.to_s}
when Module
subtract = instance_methods(true) &
other.instance_methods(true) # false?
when String, Symbol
subtract = instance_methods(true) & [other.to_s]
end
base = self
Module.new do
include base
subtract.each{ |x| undef_method x }
end
end
# Rename methods.
def *(rename_map)
base = self
Module.new do
include base
rename_map.each do |from, to|
alias_method to, from
undef_method from
end
end
end
# Detect conflicts.
#--
# TODO All instance methods, or just public?
#++
def conflict?(other)
c = []
c += (public_instance_methods(true) &
other.public_instance_methods(true))
c += (private_instance_methods(true) &
other.private_instance_methods(true))
c += (protected_instance_methods(true) &
other.protected_instance_methods(true))
c.empty ? false : c
end
#def conflict?(other)
# c = instance_methods & other.instance_methods
# c.empty ? false : c
#end
def public_conflict?(other)
c = public_instance_methods(true) &
other.public_instance_methods(true)
c.empty ? false : c
end
def private_conflict?(other)
c = private_instance_methods(true) &
other.private_instance_methods(true)
c.empty ? false : c
end
def protected_conflict?(other)
c = protected_instance_methods(true) &
other.protected_instance_methods(true)
c.empty ? false : c
end
end
Thanks,
T.