Module: JrubyScala::CoreExt::Module::Traits
- Included in:
- Module
- Defined in:
- lib/jruby_scala/core_ext/module/traits.rb
Overview
Enables the inclusion of Scala traits into Ruby modules.
TODO: Currently, JRuby throws an exception when attempting to load many of the top-level traits: List, Iterator, Equiv, Ordered, etc. Oddly enough, scala.FunctionN works fine. We need to investigate why this happens.
Class Method Summary collapse
Instance Method Summary collapse
-
#include_with_scala_trait_support(*modules) ⇒ Object
Mixes the given modules into the current module, including Scala Traits.
-
#mixin_methods_from_trait(trait_class, loader, done = Set.new) ⇒ Object
Mixes the methods from a Scala trait into the module.
Class Method Details
.included(base) ⇒ Object
15 16 17 18 19 20 |
# File 'lib/jruby_scala/core_ext/module/traits.rb', line 15 def self.included(base) base.module_eval do alias_method :include_without_scala_trait_support, :include alias_method :include, :include_with_scala_trait_support end end |
Instance Method Details
#include_with_scala_trait_support(*modules) ⇒ Object
Mixes the given modules into the current module, including Scala Traits.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/jruby_scala/core_ext/module/traits.rb', line 24 def include_with_scala_trait_support(*modules) modules.each do |m| if m.respond_to?(:java_class) and m.java_class.interface? loader = m.java_class.class_loader unless loader.nil? mixin_methods_from_trait(loader.load_class(m.java_class.to_s), loader) unless self < JrubyScala::CoreExt::OperatorTranslations include_without_scala_trait_support(JrubyScala::CoreExt::OperatorTranslations) end end end if defined?(@@trait_methods) define_method(:scala_reflective_trait_methods) {@@trait_methods} end include_without_scala_trait_support(m) end end |
#mixin_methods_from_trait(trait_class, loader, done = Set.new) ⇒ Object
Mixes the methods from a Scala trait into the module.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/jruby_scala/core_ext/module/traits.rb', line 50 def mixin_methods_from_trait(trait_class, loader, done = Set.new) return if done.include?(trait_class) done << trait_class begin klass = loader.load_class("#{trait_class.name}$class") rescue java.lang.ClassNotFoundException # Unable to load the <TraitName>$class, probably because this is # a standard Java interface, not a Scala trait, so just return. return end # TODO: Should this happen before attempting to load the special # <TraitName>$class? trait_class.interfaces.each do |iface| mixin_methods_from_trait(iface, loader, done) end klass.declared_methods.each do |meth| mods = meth.modifiers if java.lang.reflect.Modifier.static?(mods) and java.lang.reflect.Modifier.public?(mods) @@trait_methods ||= [] unless meth.name.include?('$') module_eval <<-CODE def #{meth.name}(*args, &block) args.insert(0, self) args << block unless block.nil? args.map! {|a| defined?(a.java_object) ? a.java_object : a} scala_reflective_trait_methods[#{@@trait_methods.size}].invoke(nil, args.to_java) end CODE @@trait_methods << meth else # Method name contains special characters, so use a fallback # implementation with define_method. # # Caveat: This impl can't deal with methods with function # arguments (blocks) define_method(meth.name) do |*args| args.insert(0, self) meth.invoke(nil, args.to_java) end end end end end |