On Thu, Jun 28, 2012 at 5:30 PM, Cees Zeelenberg <[email protected]> wrote: > In JRuby, I am extending an existing Java Class with a Ruby initialising > block by redefining the 'new' class method.
That does not sound like a good idea. Class#new should only be overridden if you need to adjust the initialization process. What are you trying to achieve with that? > This works fine except for new classes which inherit from the original > class and have a different number of arguments. > These classes generate a 'wrong number of arguments' error. > The behavior seems not specific for Java Classes and is actually the > same for Ruby and JRuby. > The following example illustrates it, the first version works as > expected My example irb(main):001:0> class A;end => nil irb(main):002:0> A.method :new => #<Method: Class#new> irb(main):003:0> class B<A;end => nil irb(main):004:0> B.method :new => #<Method: Class#new> irb(main):005:0> def A.new(x) printf "This won't work, but anyway %p\n", x end => nil irb(main):006:0> A.method :new => #<Method: A.new> irb(main):007:0> B.method :new => #<Method: B(A).new> irb(main):008:0> A.new 1 This won't work, but anyway 1 => nil irb(main):009:0> B.new 2 This won't work, but anyway 2 => nil irb(main):010:0> irb(main):001:0> class A;end => #<Method: Class#new> irb(main):003:0> class B<A;end => nil irb(main):004:0> B.method :new => #<Method: Class#new> irb(main):005:0> def A.new(x) printf "This won't work, but anyway %p\n", x end => nil irb(main):006:0> A.method :new => #<Method: A.new> irb(main):007:0> B.method :new => #<Method: B(A).new> irb(main):008:0> A.new 1 This won't work, but anyway 1 => nil irb(main):009:0> B.new 2 This won't work, but anyway 2 => nil > The next example adds a redefinition of Parent.new; Parent goes on to > work as expected, but Child fails: Method Class#new must always have signature (*a, &b) because otherwise it cannot properly forward arguments to #initialize. As you can see this is the case for Class#new already: irb(main):021:0> Class.method(:new).arity => -1 It has to be that way because #initialize of sub classes actually defines the signature of the constructor. Method Class#new basically does something like this: irb(main):001:0> class A irb(main):002:1> def initialize(x) @x=x end irb(main):003:1> def self.new(*a,&b) irb(main):004:2> puts "before" irb(main):005:2> x = allocate irb(main):006:2> printf "allocated %p\n", x irb(main):007:2> x.send(:initialize, *a, &b) irb(main):008:2> printf "initialized %p\n", x irb(main):009:2> x irb(main):010:2> end irb(main):011:1> end => nil irb(main):012:0> e = A.new 123 before allocated #<A:0x80319e78> initialized #<A:0x80319e78 @x=123> => #<A:0x80319e78 @x=123> There is only reason if you want to change allocation of instances of a class (e.g. by taking them from a pool of preallocated instances or such). This is rarely the case. > Is this behavior intentional or a bug? At least it is consistent (Ruby > 1.8.7, 1.9.1 JRuby 1.6.7) I think it is intentional and consistent because if you introduce specific storage characteristics for a class you'll likely want all subclasses to share it. The same happens with singleton methods of class instances generally: irb(main):001:0> class A;end => nil irb(main):002:0> class B<A;end => nil irb(main):003:0> A.methods.grep /foo/ => [] irb(main):004:0> B.methods.grep /foo/ => [] irb(main):005:0> def A.foo() puts 123 end => nil irb(main):006:0> A.foo 123 => nil irb(main):007:0> A.methods.grep /foo/ => [:foo] irb(main):008:0> B.methods.grep /foo/ => [:foo] irb(main):009:0> B.foo 123 => nil That way properties you define on a class are available for subclasses as well. irb(main):010:0> class <<A; attr_accessor :bar end => nil irb(main):011:0> A.bar=9 => 9 irb(main):012:0> B.bar => nil irb(main):013:0> B.bar=123 => 123 irb(main):014:0> B.bar => 123 > I have tried using alias instead of super and changing the order of > redefining new and defining initialize. I also tried using class_eval > and taking the Person.new definition out of the original class > definition. All to no avail. > Any help would be appreciated. Please first explain what your goal is. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/ -- You received this message because you are subscribed to the Google Groups ruby-talk-google group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at https://groups.google.com/d/forum/ruby-talk-google?hl=en
