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

Reply via email to