Discussion:
does Ruby not support multiple "initialize" methods for a class???
Greg Hauptmann
2007-03-20 11:54:38 UTC
Permalink
Hi,

Q1 - Does Ruby not support multiple "initialize" methods for a class?

Q2 - If no is there a reason for this out of curiosity?

Q3 - What approach is recommended if this constraint does exist?

Cheers
Greg
Eivind Eklund
2007-03-20 12:06:55 UTC
Permalink
Post by Greg Hauptmann
Q1 - Does Ruby not support multiple "initialize" methods for a class?
Q2 - If no is there a reason for this out of curiosity?
Q3 - What approach is recommended if this constraint does exist?
I am not sure what you want to achieve here. There is nothing magic
about initialize; it is just a method that is called from new. Maybe
you're talking of multiple new methods instead of multiple initialize
methods?

new used to be magic; however, the magic has been moved, so these days
new is the same as

def Class.new(*args)
object = allocate
object.initialize(*args)
object
end

with "allocate" being the 'magic' method to allocate new objects.
With this, you can easily create multiple new methods, too.

Eivind.
Alex Young
2007-03-20 12:08:52 UTC
Permalink
Post by Greg Hauptmann
Hi,
Q1 - Does Ruby not support multiple "initialize" methods for a class?
No.
Post by Greg Hauptmann
Q2 - If no is there a reason for this out of curiosity?
Method overloading isn't supported in general - it's not just constructors.
Post by Greg Hauptmann
Q3 - What approach is recommended if this constraint does exist?
Default values and varargs, options hashes, or different class
hierarchies. It depends on exactly what you're trying to achieve. Do
you have an example?
--
Alex
hemant
2007-03-20 12:11:45 UTC
Permalink
Post by Greg Hauptmann
Hi,
Q1 - Does Ruby not support multiple "initialize" methods for a class?
Q2 - If no is there a reason for this out of curiosity?
Q3 - What approach is recommended if this constraint does exist?
Cheers
Greg
ruby doesn't have method overloading. So no multiple initialize methods.

Out of curiosity, why you need multiple initialize methods in a
language like ruby?
Greg Hauptmann
2007-03-20 12:26:55 UTC
Permalink
I have a class that can be created from a couple of scenarios, and for each
the initial data to populate the class is different. I was going to create
two "initialize" methods with their own specific method signature to cover
off these two scenarios however I guess I will need to perhaps just create
two separate/normal methods for this. Perhaps then it would be like:

a = Klass.new
a.create_for_scenario_one (...)
Stefano Crocco
2007-03-20 12:35:24 UTC
Permalink
Post by Greg Hauptmann
I have a class that can be created from a couple of scenarios, and for each
the initial data to populate the class is different. I was going to create
two "initialize" methods with their own specific method signature to cover
off these two scenarios however I guess I will need to perhaps just create
a = Klass.new
a.create_for_scenario_one (...)
You could just declare an initialize method which takes any number of
arguments, then detect the scenario according to the passed argument. For
example, assuming that in one case the first argument is a number and in the
second is a string, you could do:

class MyClass

def initialize(*args)
if args[0].is_a? Numeric
#perform initialization in first case
elsif args[0].is_a? String
#perform initialization in second case
else raise TypeError
end
end

end

I hope this helps

Stefano
Avdi Grimm
2007-03-20 14:09:31 UTC
Permalink
Post by Stefano Crocco
You could just declare an initialize method which takes any number of
arguments, then detect the scenario according to the passed argument. For
example, assuming that in one case the first argument is a number and in the
class MyClass
def initialize(*args)
if args[0].is_a? Numeric
#perform initialization in first case
elsif args[0].is_a? String
#perform initialization in second case
else raise TypeError
end
end
This looks a lot nicer using "case":

class MyClass

def initialize(*args)
case args0
when Numeric
# ...perform numeric initialization
when String
# ...perform string initialization
else
raise TypeError
end
end

end

Of course, you can get a lot fancier with your "case" statement using
regular expressions, ranges, multiple matchers per case, etc. The sky's the
limit...

--
Avdi
Gary Wright
2007-03-20 13:23:23 UTC
Permalink
Post by Greg Hauptmann
I have a class that can be created from a couple of scenarios, and for each
the initial data to populate the class is different. I was going to create
two "initialize" methods with their own specific method signature to cover
off these two scenarios however I guess I will need to perhaps just create
Eivind had your answer. Use new/initialize for one version of your
constructor and then roll your own for the second version:

class Myclass

def self.new2(*args)
object = allocate
object.initialize2(*args)
object
end

def initialize2(*args)
# other initialization code
end
end


Gary Wright
Austin Ziegler
2007-03-20 13:51:06 UTC
Permalink
Post by Greg Hauptmann
I have a class that can be created from a couple of scenarios, and for each
the initial data to populate the class is different. I was going to create
two "initialize" methods with their own specific method signature to cover
off these two scenarios however I guess I will need to perhaps just create
a = Klass.new
a.create_for_scenario_one (...)
a = Klass.create_scenario_one(...)
b = Klass.create_scenario_two(...)

That's the more common idiom in Ruby.

-austin
--
Austin Ziegler * ***@gmail.com * http://www.halostatue.ca/
* ***@halostatue.ca * http://www.halostatue.ca/feed/
* ***@zieglers.ca
a***@noaa.gov
2007-03-20 14:42:06 UTC
Permalink
Post by Greg Hauptmann
I have a class that can be created from a couple of scenarios, and for each
the initial data to populate the class is different. I was going to create
two "initialize" methods with their own specific method signature to cover
off these two scenarios however I guess I will need to perhaps just create
a = Klass.new
a.create_for_scenario_one (...)
you can use class methods to return objects, as others have mentioned, but it
also extremely easy to do your own function signature matching in ruby

harp:~ > cat a.rb
class C
def initialize *argv, &block
case argv
when match(Fixnum)
initialize_from_int argv[0]
when match(Fixnum, Float)
initialize_from_int_float argv[0], argv[1]
else
raise ArgumentError, argv.inspect
end
end

def initialize_from_int int
@int = int
@float = 0.0
end

def initialize_from_int_float int, float
@int = int
@float = float
end

class Pattern
def initialize template
@template = template
end
def === objects
return false unless @template.size == objects.size
@template.each_with_index do |pat, idx|
return false unless pat === objects[idx]
end
return true
end
end
def match *template
Pattern.new template
end
end

p C.new(42)
p C.new(42,42.0)



harp:~ > ruby a.rb
#<C:0xb75cff08 @float=0.0, @int=42>
#<C:0xb75cfcd8 @float=42.0, @int=42>


however, function signature overloading is very confusing when mixed with
default parameters. most people simply ignore this and live with the bugs in
c++.

regards.

-a
--
be kind whenever possible... it is always possible.
- the dalai lama
Mat Schaffer
2007-03-20 16:15:36 UTC
Permalink
Post by a***@noaa.gov
Post by Greg Hauptmann
I have a class that can be created from a couple of scenarios, and for each
the initial data to populate the class is different. I was going to create
two "initialize" methods with their own specific method signature to cover
off these two scenarios however I guess I will need to perhaps just create
a = Klass.new
a.create_for_scenario_one (...)
you can use class methods to return objects, as others have mentioned, but it
also extremely easy to do your own function signature matching in ruby
In the interest of ridiculousness, how about using the multi gem for
this? :)

require 'rubygems'
require 'multi'

class Foo
def initialize(*args)
multi(:init, Integer) { |i|
puts 'integer used'
# do integer stuff...
}

multi(:init, Float) { |f|
puts 'float used'
# do float stuff...
}

init(*args)
end
end
Daniel Berger
2007-03-20 16:45:08 UTC
Permalink
On Mar 20, 10:15 am, "Mat Schaffer" <***@gmail.com> wrote:

<snip>
Post by Mat Schaffer
In the interest of ridiculousness, how about using the multi gem for
this? :)
require 'rubygems'
require 'multi'
class Foo
def initialize(*args)
multi(:init, Integer) { |i|
puts 'integer used'
# do integer stuff...
}
multi(:init, Float) { |f|
puts 'float used'
# do float stuff...
}
init(*args)
end
end
Heh, that interface is very similar to Nobu's overload package. [1]
There's also Ryan's strongtyping package for simulating overloaded
methods. [2]

Regards,

Dan

[1] http://www.rubyist.net/~nobu/ruby/overload-0.6.tar.bz2
[2] http://raa.ruby-lang.org/project/strongtyping/

PS - Nobu, you need to update your RAA link for the overload
package. :)
Emilio Tagua
2007-03-20 13:55:10 UTC
Permalink
Post by Greg Hauptmann
Hi,
Q1 - Does Ruby not support multiple "initialize" methods for a class?
Q2 - If no is there a reason for this out of curiosity?
Q3 - What approach is recommended if this constraint does exist?
You could use:

class Invitation
attr_reader :id, :date, :user, :text, :email

def Invitation.withId(id)
return self.new(id)
end

def Invitation.withAll(id, date, user, email, text)
return self.new(id, date, user, email, text)
end

def initialize(id = 0, date = '', user = '', email = '', text = '')
super()
@id = id
@date = date
@email = email
@user = user
@text = text
end
end

then:

invitation = Invitation.withId(1)

or with all params.
Rick DeNatale
2007-03-20 14:25:21 UTC
Permalink
Post by Emilio Tagua
class Invitation
attr_reader :id, :date, :user, :text, :email
def Invitation.withId(id)
return self.new(id)
end
def Invitation.withAll(id, date, user, email, text)
return self.new(id, date, user, email, text)
end
def initialize(id = 0, date = '', user = '', email = '', text = '')
super()
@id = id
@date = date
@email = email
@user = user
@text = text
end
end
invitation = Invitation.withId(1)
or with all params.
Of course the only thing that the withId and withAll (*which in more
normal Ruby style should be with_id and with _all) do is throw an
error if you don't call them with the right number of parameters.

With the above code you can also write:

Invitation.new
Invitation.new(42)
Invitation.new(99, '10/22/2006')
Invitation.new(35, '3/2/1907', 'Teddy Roosevelt')
Invitation.new(67, '10/12/2010', 'Arthur C. Clarke', '***@theFuture.org')
or
Invitation.new(88, '6/6/1945', 'Dwight Eisenhower', '***@us.mil',
'I like Ike')

Any of these work as defaults are provide dor all.

Another approach would be to use a Hash to provide 'keyword' arguments.

Invitation.new(:id => 20, :email => '***@somewhere.com')

The initialize method would need to pick the hash argument apart.

def initialize(options={})
# process options and set iv's etc.
end

You could combine this with additional parameters before the hash parameter.

* Normal ruby style is to reserve 'camel case' for Globals (e.g. class
and module names) and use underscores as separators in variable names.
I keep tripping up on that when my old Smalltalk habits kick in.
It's not crucial, but when in Ruby do as the Rubyists do.
--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/
j***@gmail.com
2007-03-20 23:32:37 UTC
Permalink
Post by Greg Hauptmann
Hi,
Q1 - Does Ruby not support multiple "initialize" methods for a class?
Q2 - If no is there a reason for this out of curiosity?
Q3 - What approach is recommended if this constraint does exist?
I have been using the following pattern to implement multiple
constructors for a class. It is only a variation of the already
proposed solutions, but by using "instance_eval" I could avoid having
to create separate new/initialize-like methods for each constructor.

/Johan Holmberg

#-------------------------------
class Point

def self.create_cartesian(x,y)
allocate.instance_eval do
@x = x
@y = y
self
end
end

def self.create_polar(length,angle)
allocate.instance_eval do
@x = length * Math.cos(angle)
@y = length * Math.sin(angle)
self
end
end

end
#-------------------------------
Chad Perrin
2007-03-21 01:09:36 UTC
Permalink
Post by j***@gmail.com
Post by Greg Hauptmann
Hi,
Q1 - Does Ruby not support multiple "initialize" methods for a class?
Q2 - If no is there a reason for this out of curiosity?
Q3 - What approach is recommended if this constraint does exist?
I have been using the following pattern to implement multiple
constructors for a class. It is only a variation of the already
proposed solutions, but by using "instance_eval" I could avoid having
to create separate new/initialize-like methods for each constructor.
I've heard it said -- and I tend to agree -- that regular use of
"patterns" is a sign that the language lacks something. I wonder if
that is the case with Ruby, as applies to multiple constructor behavior
implementation.

I say "wonder" because I really am not certain in this case.
--
CCD CopyWrite Chad Perrin [ http://ccd.apotheon.org ]
Leon Festinger: "A man with a conviction is a hard man to change. Tell
him you disagree and he turns away. Show him facts and figures and he
questions your sources. Appeal to logic and he fails to see your point."
Gregory Seidman
2007-03-21 01:25:20 UTC
Permalink
Post by Chad Perrin
Post by j***@gmail.com
Post by Greg Hauptmann
Hi,
Q1 - Does Ruby not support multiple "initialize" methods for a class?
Q2 - If no is there a reason for this out of curiosity?
Q3 - What approach is recommended if this constraint does exist?
I have been using the following pattern to implement multiple
constructors for a class. It is only a variation of the already
proposed solutions, but by using "instance_eval" I could avoid having
to create separate new/initialize-like methods for each constructor.
I've heard it said -- and I tend to agree -- that regular use of
"patterns" is a sign that the language lacks something. I wonder if
that is the case with Ruby, as applies to multiple constructor behavior
implementation.
I say "wonder" because I really am not certain in this case.
Well, it's a choice. You can either have overloading or dynamic typing, but
not both. The "pattern" is just a matter of having different names for your
constructors. The simple, common case of a single constructor is supported
by the new/initialize separation, but multiple constructors are still
pretty easy. Note that Objective-C, another Smalltalk-like,
dynamically-typed language, uses the same pattern.
Post by Chad Perrin
CCD CopyWrite Chad Perrin [ http://ccd.apotheon.org ]
--Greg
Daniel Berger
2007-03-21 01:36:05 UTC
Permalink
Post by Gregory Seidman
Post by Chad Perrin
Post by j***@gmail.com
Post by Greg Hauptmann
Hi,
Q1 - Does Ruby not support multiple "initialize" methods for a class?
Q2 - If no is there a reason for this out of curiosity?
Q3 - What approach is recommended if this constraint does exist?
I have been using the following pattern to implement multiple
constructors for a class. It is only a variation of the already
proposed solutions, but by using "instance_eval" I could avoid having
to create separate new/initialize-like methods for each constructor.
I've heard it said -- and I tend to agree -- that regular use of
"patterns" is a sign that the language lacks something. I wonder if
that is the case with Ruby, as applies to multiple constructor behavior
implementation.
I say "wonder" because I really am not certain in this case.
Well, it's a choice. You can either have overloading or dynamic typing, but
not both.
Not true. Perl 6 will have optional static typing [1]. Sydney faked it
with a Behavior you could import (that used the parser to handle it, not
a compile time step, IIRC).

It's possible. The question is whether or not it's desirable. I vote
yes, others say no, and still others are in favor of some sort of type
inferencing. It's been brought up before - you can search the archives. :)

Regards,

Dan

[1] http://www.perl.com/pub/a/2007/03/01/perl-6-parameter-passing.html
Chad Perrin
2007-03-21 02:11:53 UTC
Permalink
Post by Daniel Berger
Not true. Perl 6 will have optional static typing [1]. Sydney faked it
with a Behavior you could import (that used the parser to handle it, not
a compile time step, IIRC).
It's possible. The question is whether or not it's desirable. I vote
yes, others say no, and still others are in favor of some sort of type
inferencing. It's been brought up before - you can search the archives. :)
I'm a fan of Ruby's dynamic typing. When I want type inference, I use
OCaml instead. My thought is not that I should have one language that
does everything, but that each language I have available is optimally
useful for the tasks in which I choose to employ it.

That being said . . . I'm not saying we should necessarily have
overloading in Ruby. I just wonder if there might be another way to
solve the same problem without having to resort to development patterns
to "work around" a lack of easy functionality. I'm not entirely sold on
the idea that there's enough "working around" to bother in this case,
but there might be.

Thus, my question.
--
CCD CopyWrite Chad Perrin [ http://ccd.apotheon.org ]
unix virus: If you're using a unixlike OS, please forward
this to 20 others and erase your system partition.
David A. Black
2007-03-21 03:27:04 UTC
Permalink
Hi --
Post by Chad Perrin
Post by Daniel Berger
Not true. Perl 6 will have optional static typing [1]. Sydney faked it
with a Behavior you could import (that used the parser to handle it, not
a compile time step, IIRC).
It's possible. The question is whether or not it's desirable. I vote
yes, others say no, and still others are in favor of some sort of type
inferencing. It's been brought up before - you can search the archives. :)
I'm a fan of Ruby's dynamic typing. When I want type inference, I use
OCaml instead. My thought is not that I should have one language that
does everything, but that each language I have available is optimally
useful for the tasks in which I choose to employ it.
That being said . . . I'm not saying we should necessarily have
overloading in Ruby. I just wonder if there might be another way to
solve the same problem without having to resort to development patterns
to "work around" a lack of easy functionality. I'm not entirely sold on
the idea that there's enough "working around" to bother in this case,
but there might bere
Thus, my question.
I think the availability of the allocate method is very characteristic
of Ruby, and not a workaround. It's just Ruby being Ruby. One thing
I've always loved about Ruby is that it lets you do things through
composition of simple techniques that are virtually equivalent to
language-level constructs and facilities in other languages. The
classic examples are "attributes" and "class methods." All you need
to create attributes in Ruby is:

1. instance variables
2. methods

and (almost) all you need for class methods (except a bit of
inheritance special-casing) is:

1. objects can have singleton methods
2. classes are objects.

It's like Ruby is saying, "You want 'attributes'? OK. Here. Now
you've got 'attributes'." :-) It's all built on the simplest possible
things in Ruby, and on not very many of them.

Multiple constructors seem to fall into that category. All you have
to do is use allocate, and you can have as many constructors as you
need.

I wonder what lies ahead. I mean, look how easy it is to conjure up
things like attributes and class methods from the building blocks that
Ruby offers. The things that get conjured up tend to resemble things
from other languages -- but maybe there are entirely new constructs
waiting to arise out of Ruby's components.


David
--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
Chad Perrin
2007-03-21 18:08:56 UTC
Permalink
Post by David A. Black
It's like Ruby is saying, "You want 'attributes'? OK. Here. Now
you've got 'attributes'." :-) It's all built on the simplest possible
things in Ruby, and on not very many of them.
Multiple constructors seem to fall into that category. All you have
to do is use allocate, and you can have as many constructors as you
need.
I wonder what lies ahead. I mean, look how easy it is to conjure up
things like attributes and class methods from the building blocks that
Ruby offers. The things that get conjured up tend to resemble things
from other languages -- but maybe there are entirely new constructs
waiting to arise out of Ruby's components.
Hmm. I like that explanation. It'll bear some thought.

Thanks.
--
CCD CopyWrite Chad Perrin [ http://ccd.apotheon.org ]
"A script is what you give the actors. A program
is what you give the audience." - Larry Wall
Rick DeNatale
2007-03-21 19:08:02 UTC
Permalink
Post by David A. Black
I wonder what lies ahead. I mean, look how easy it is to conjure up
things like attributes and class methods from the building blocks that
Ruby offers. The things that get conjured up tend to resemble things
from other languages -- but maybe there are entirely new constructs
waiting to arise out of Ruby's components.
This statement reminds me of something Alan Kay said to me after he
had given a talk on Smalltalk at IBM. He said that one of his
disappointments was that no one ever seemed to make new subclasses of
Behavior (which in Smalltalk is the abstract class which both Class
and Metaclass subclass).
--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/
Nando Sanchez
2007-03-21 01:30:56 UTC
Permalink
Post by Chad Perrin
Post by j***@gmail.com
I have been using the following pattern to implement multiple
constructors for a class. It is only a variation of the already
proposed solutions, but by using "instance_eval" I could avoid having
to create separate new/initialize-like methods for each constructor.
I've heard it said -- and I tend to agree -- that regular use of
"patterns" is a sign that the language lacks something. I wonder if
that is the case with Ruby, as applies to multiple constructor behavior
implementation.
I say "wonder" because I really am not certain in this case.
Hi Chad! I don't think Ruby "lacks" anything, it's just that it has a
different way of doing things. It's a trade-off between the flexibility
of a dynamic language and some other things like methods with same name
and different parameters (how are you going to distinguish between one
method that uses a string and an integer and another one that uses an
integer and a hash, if you don't have types defined at the parameter
level?). If you want to do things "like Java" or "like C++", then I
think you should open your mind and try to do things in a different way,
in a rubbish way.

Regards,

Nando
--
Posted via http://www.ruby-forum.com/.
Daniel Berger
2007-03-21 01:38:44 UTC
Permalink
Nando Sanchez wrote:

<snip>
Post by Nando Sanchez
Hi Chad! I don't think Ruby "lacks" anything, it's just that it has a
different way of doing things. It's a trade-off between the flexibility
of a dynamic language and some other things like methods with same name
and different parameters (how are you going to distinguish between one
method that uses a string and an integer and another one that uses an
integer and a hash, if you don't have types defined at the parameter
level?). If you want to do things "like Java" or "like C++", then I
think you should open your mind and try to do things in a different way,
in a rubbish way.
^^^^^^^

I think you mean "ruby-ish". :)

Dan
Chad Perrin
2007-03-21 18:10:37 UTC
Permalink
Post by Nando Sanchez
Hi Chad! I don't think Ruby "lacks" anything, it's just that it has a
different way of doing things. It's a trade-off between the flexibility
of a dynamic language and some other things like methods with same name
and different parameters (how are you going to distinguish between one
method that uses a string and an integer and another one that uses an
integer and a hash, if you don't have types defined at the parameter
level?). If you want to do things "like Java" or "like C++", then I
think you should open your mind and try to do things in a different way,
in a rubbish way.
Trust me -- I have no interest in shoehorning anything into a Java or
C++ mold. That wasn't my point.
--
CCD CopyWrite Chad Perrin [ http://ccd.apotheon.org ]
"The first rule of magic is simple. Don't waste your time waving your
hands and hopping when a rock or a club will do." - McCloctnick the Lucid
Florian Frank
2007-03-21 21:06:38 UTC
Permalink
Post by Chad Perrin
I've heard it said -- and I tend to agree -- that regular use of
"patterns" is a sign that the language lacks something. I wonder if
that is the case with Ruby, as applies to multiple constructor behavior
implementation.
I don't consider this to be a pattern, I consider overloading
constructors an anti-pattern.

One of the few good Java books (among all the mediocre or even worse
ones) is "Effective Java" by Joshua Bloch:

http://java.sun.com/docs/books/effective/toc.html

In the first chapter (actually chapter 2) in the first item Bloch
advises Java programmers to consider using static factory methods
instead of public and/or overloaded constructors. He lists the following
advantages:

: One advantage of static factory methods is that, unlike constructors,
they have names.
: If the parameters to a constructor do not, in and of themselves,
describe the object being
: returned, a static factory with a well-chosen name can make a class
easier to use and the
: resulting client code easier to read.
: [...]

The same is true in Ruby, if you use class methods (methods of a class's
eigenclass). The workarounds in the initialize method even *look* code
smelly. In Java overloading a constructor once or twice doesn't seem to
be such a bad idea. But other programmers tend to just copy and paste
another constructor below the others. Once you have a class that comes
into the two digit range of constructors, it gets quite difficult to
remember all the different possible permutations of types. (Yes, I had
to maintain code like that.)

And I think, overloading in general isn't such a good idea either. It
can lead to really funny semantic errors, if it teams up with Java's
numeric type promotion for example. (Yeah, this happened to me, too.)

: A second advantage of static factory methods is that, unlike
constructors, they are not
: required to create a new object each time they're invoked. This allows
immutable classes
: (Item 13) to use preconstructed instances or to cache instances as
they're constructed and to
: dispense these instances repeatedly so as to avoid creating
unnecessary duplicate objects.

This is an advantage in Java only, in Ruby "constructors" already have
this advantage, the are actually factory methods - and classes are
nothing but object factories, objects that can make other objects. Ruby
doesn't have "real" constructors like Java has. In Ruby a "constructor"
is a simple method, defined in class Class and thus can be shadowed by
defining a method in a class's eigenclass, where new objects can be
allocated, configured, cached, and so on. These changes are also
transparent for client code, which doesn't have to be changed to, e. g.,
profit from caching.

: A third advantage of static factory methods is that, unlike
constructors, they can return
: an object of any subtype of their return type. This gives you great
flexibility in choosing
: he class of the returned object.

This is a Java advantage only, because Ruby doesn't have to work around
a rigid type system. You just have to take care not to screw up.

: One application of this flexibility is that an API can return objects
without making their
: classes public. Hiding implementation classes in this fashion can lead
to a very compact API.
: This technique lends itself to interface-based frameworks, where
interfaces provide natural
: return types for static factory methods.

Can be done in Ruby as well for both "new" factory methods or better
named factory methods.

: The main disadvantage of static factory methods is that classes
without public or
: protected constructors cannot be subclassed.
: [...]

This isn't a disadvantage in Ruby, because private methods *can* be
called from subclasses.

: A second disadvantage of static factory methods is that they are not
readily
: distinguishable from other static methods. They do not stand out in
API documentation in
: the way that constructors do. Furthermore, static factory methods
represent a deviation from
: the norm. Thus it can be difficult to figure out from the class
documentation how to instantiate
: a class that provides static factory methods instead of constructors.
This disadvantage can be
: reduced by adhering to standard naming conventions.

This might be a disadvantage, but you should choose meaningful names for
all methods and document accordingly anyway.
--
Florian Frank
a***@noaa.gov
2007-03-21 21:28:45 UTC
Permalink
I don't consider this to be a pattern, I consider overloading constructors
an anti-pattern.
One of the few good Java books (among all the mediocre or even worse ones)
http://java.sun.com/docs/books/effective/toc.html
In the first chapter (actually chapter 2) in the first item Bloch advises
Java programmers to consider using static factory methods instead of public
: One advantage of static factory methods is that, unlike constructors, they
have names.
: If the parameters to a constructor do not, in and of themselves, describe
the object being
: returned, a static factory with a well-chosen name can make a class easier
to use and the
: resulting client code easier to read.
: [...]
The same is true in Ruby, if you use class methods (methods of a class's
eigenclass). The workarounds in the initialize method even *look* code
smelly. In Java overloading a constructor once or twice doesn't seem to be
such a bad idea. But other programmers tend to just copy and paste another
constructor below the others. Once you have a class that comes into the two
digit range of constructors, it gets quite difficult to remember all the
different possible permutations of types. (Yes, I had to maintain code like
that.)
And I think, overloading in general isn't such a good idea either. It can
lead to really funny semantic errors, if it teams up with Java's numeric
type promotion for example. (Yeah, this happened to me, too.)
and this doesn't even take into account the confusion that can be heaped upon
the programmer when default parameters are thrown into the mix. if parameter
overloading were allowed in ruby we could have this:

def m int
p int
p 42.0
end

def m int, float = 42.0
p int
p float
end

m 42

now, which one is called? in order to understand this kind of stuff in c++
you have to become the compiler.

it's even worse when you can do

m *args # yikes, which one is called?

no thanks!

cheers.

-a
--
be kind whenever possible... it is always possible.
- the dalai lama
John Joyce
2007-03-21 23:10:47 UTC
Permalink
Why do people want to do this? Other than just to do it. What was it
about C letting you shoot yourself in the foot, and C++ letting you
blow your whole leg off...
Post by a***@noaa.gov
Post by Florian Frank
I don't consider this to be a pattern, I consider overloading
constructors
an anti-pattern.
One of the few good Java books (among all the mediocre or even worse ones)
http://java.sun.com/docs/books/effective/toc.html
In the first chapter (actually chapter 2) in the first item Bloch advises
Java programmers to consider using static factory methods instead of public
: One advantage of static factory methods is that, unlike
constructors, they have names.
: If the parameters to a constructor do not, in and of themselves,
describe the object being
: returned, a static factory with a well-chosen name can make a
class easier to use and the
: resulting client code easier to read.
: [...]
The same is true in Ruby, if you use class methods (methods of a class's
eigenclass). The workarounds in the initialize method even *look* code
smelly. In Java overloading a constructor once or twice doesn't seem to be
such a bad idea. But other programmers tend to just copy and paste another
constructor below the others. Once you have a class that comes into the two
digit range of constructors, it gets quite difficult to remember all the
different possible permutations of types. (Yes, I had to maintain code like
that.)
And I think, overloading in general isn't such a good idea either. It can
lead to really funny semantic errors, if it teams up with Java's numeric
type promotion for example. (Yeah, this happened to me, too.)
and this doesn't even take into account the confusion that can be heaped upon
the programmer when default parameters are thrown into the mix. if parameter
def m int
p int
p 42.0
end
def m int, float = 42.0
p int
p float
end
m 42
now, which one is called? in order to understand this kind of
stuff in c++
you have to become the compiler.
it's even worse when you can do
m *args # yikes, which one is called?
no thanks!
cheers.
-a
--
be kind whenever possible... it is always possible.
- the dalai lama
Avdi Grimm
2007-03-22 02:28:31 UTC
Permalink
Post by a***@noaa.gov
def m int
p int
p 42.0
end
def m int, float = 42.0
p int
p float
end
m 42
now, which one is called? in order to understand this kind of stuff in c++
you have to become the compiler.
Speaking with my C++ compiler hat on, I believe the answer is "Ambiguous
function call; please be more specific" (your compiler error may vary).

But your point is well-taken.
--
Avdi
Continue reading on narkive:
Loading...