Class with Multi Constrcutor ( initialize )

M

Mido Peace

Hey ..
I'm Tryin' to port Some Java Module into Ruby , but I have a small
probleme ,
how can I do to declare multi 'initialize Method' depending of the
number of user
argument

i.e in Java we can have a Class with many constructor
class myClass {

//...
public MyClass () { ... } // Defualt One
public MyClass (Object obj1 ) { ... }
public myClass ( Object obj1,Object obj2 ...,Object objn) { ... }
// ...
}

I tried :
class myClass
def initialize ()
// ...
end

def intialize ( value )
// ...
end
end

but doesnt works !

I just wanna find a way to call the right constructor ( or initializer)
depending of the number of arguments


Thx ;)
 
J

Jesús Gabriel y Galán

Hey ..
I'm Tryin' to port Some Java Module into Ruby , but I have a small
probleme ,
how can I do to declare multi 'initialize Method' depending of the
number of user
argument

i.e in Java we can have a Class with many constructor
class myClass {

=A0 //...
=A0 =A0public MyClass () { ... } =A0// Defualt One
=A0 =A0public MyClass (Object obj1 ) { ... }
=A0 =A0public myClass =A0( Object obj1,Object obj2 ...,Object objn) { ...= }
=A0// ...
}

I tried :
class myClass
=A0 def initialize ()
=A0 =A0 // ...
=A0 end

=A0 def intialize ( value )
=A0 =A0// ...
=A0 end
end

but doesnt works !

I just wanna find a way to call the right constructor ( or initializer)
depending of the number of arguments

Ruby doesn't support method overloading. If you need different
implementations just depending on the number of arguments you can do:

class MyClass
def initialize *args
case args.size
when 1
_init_1_param *args
when 2
_init_2_params *args
....
end
end

or you can do this:

class MyClass
def initialize(options =3D {})
# and have the logic depend on the keys present in the hash
end
end

So you can call:

MyClass.new
MyClass.new:)obj1 =3D> some_object, :eek:bj2 =3D> some_other_object)

Hope this helps,

Jesus.
 
J

Jesús Gabriel y Galán

Checking old emails on the matter, I like this approach a lot:

If you have different ways of constructing objects of a class, create
different class methods to do so. For example:

class MyClass
def self.from_x_y(x,y)
MyClass.new(x,y)
end

def self.default
MyClass.new(0,0)
end

def self.from_point(p)
MyClass.new(p.x, p.y)
end

def initialize(x,y)
@x = x
@y = y
end
end

This way you can have:

MyClass.default #=> 0,0
MyClass.from_x_y(10,20) # => 10,20
MyClass.from_point(Point.new(1,2)) #=> 1,2

Hope this helps,

Jesus.
 
P

Pierre Lecocq

Hello Mido,

There are several solutions to this problem.

The first one is this equivalent of vaargs in C language

def initialize(*args)
args.each do |a|
puts a.class.inspect
end
end

The second one is to pass a hash or an array in parameter.

And the third is to put default values to your args:

def initialize(var1='', var2=0, var3=nil)
end

Hope i helped !

Kind regards
 
R

Robert Klemme

Hello Mido,

There are several solutions to this problem.

The first one is this equivalent of vaargs in C language

def initialize(*args)
args.each do |a|
puts a.class.inspect
end
end

The second one is to pass a hash or an array in parameter.

And the third is to put default values to your args:

def initialize(var1='', var2=0, var3=nil)
end

Hope i helped !

A solution like this was proposed for overloading once but it does not
seem to be widely used:

irb(main):001:0> def overload(*a)
irb(main):002:1> case a.map {|x|x.class}
irb(main):003:2> when [String]
irb(main):004:2> puts "a single string"
irb(main):005:2> when [Fixnum, String]
irb(main):006:2> puts a[1] * a[0]
irb(main):007:2> else
irb(main):008:2* raise ArgumentError, "can't %p" % a
irb(main):009:2> end
irb(main):010:1> end
=> nil
irb(main):011:0> overload "foo"
a single string
=> nil
irb(main):012:0> overload 2, "foo"
foofoo
=> nil
irb(main):013:0> overload 2
ArgumentError: can't 2
from (irb):8:in `overload'
from (irb):13
from /usr/local/bin/irb19:12:in `<main>'
irb(main):014:0>

You can even shorten that to

case a.map(&:class)
....

Kind regards

robert
 
A

Albert Schlef

Robert said:
A solution like this was proposed for overloading once but it does not
seem to be widely used:

irb(main):001:0> def overload(*a)
irb(main):002:1> case a.map {|x|x.class}
irb(main):003:2> when [String]
irb(main):004:2> puts "a single string"
irb(main):005:2> when [Fixnum, String]

Cool. Where is "Array#===" documented? I couldn't find it.
 
G

Gary Wright

Robert said:
A solution like this was proposed for overloading once but it does not
seem to be widely used:

irb(main):001:0> def overload(*a)
irb(main):002:1> case a.map {|x|x.class}
irb(main):003:2> when [String]
irb(main):004:2> puts "a single string"
irb(main):005:2> when [Fixnum, String]

Cool. Where is "Array#===" documented? I couldn't find it.

Unfortunately Array#=== is just the same as Array#==, which is
why the argument list is mapped to class objects via #map in that
example from Robert.

There was a somewhat recent thread about changing Array#=== to
be an element-wise application of ===, which makes a lot of
sense to me.

Gary Wright
 
A

Albert Schlef

Gary said:
Unfortunately Array#=== is just the same as Array#==,

So it isn't cool. "when [Integer, Integer]" won't match any integer
numbers :-(
There was a somewhat recent thread about changing Array#=== to
be an element-wise application of ===, which makes a lot of
sense to me.

to me too.
 
R

Robert Klemme

2010/1/28 Albert Schlef said:
Gary said:
Unfortunately Array#=== is just the same as Array#==,

So it isn't cool. "when [Integer, Integer]" won't match any integer
numbers :-(
There was a somewhat recent thread about changing Array#=== to
be an element-wise application of ===, which makes a lot of
sense to me.

to me too.

Even if that would not happen you could do this and benefit from a
more efficient approach because tests are constants:

def MultiCheck(*a)
def a.===(b)
zip(b) {|x,y| return false unless x === y}
true
end
a.freeze
end

irb(main):023:0> T1 = MultiCheck String
=> [String]
irb(main):024:0> T2 = MultiCheck Fixnum, String
=> [Fixnum, String]
irb(main):025:0> def overload(*a)
irb(main):026:1> case a
irb(main):027:2> when T1
irb(main):028:2> puts "a single string"
irb(main):029:2> when T2
irb(main):030:2> puts a[1] * a[0]
irb(main):031:2> else
irb(main):032:2* raise ArgumentError, "can't %p" % a
irb(main):033:2> end
irb(main):034:1> end
=> nil
irb(main):035:0> overload "foo"
a single string
=> nil
irb(main):036:0> overload 2, "foo"
foofoo
=> nil
irb(main):037:0> overload 2
ArgumentError: can't 2
from (irb):32:in `overload'
from (irb):37
from /opt/bin/irb19:12:in `<main>'
irb(main):038:0>

:)

Note, the same approach also works with regular expressions as
elements in the MultiCheck Array.

Cheers

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top