Forum: Ruby private #initialize

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
B1b1d33e0655e841d4fd8467359c58d0?d=identicon&s=25 Yossef Mendelssohn (Guest)
on 2008-11-27 21:44
(Received via mailing list)
My apologies if this has been discussed before, but I couldn't find
anything in a Google search, searching this particular list/group on
Google, or my first attempt at blade. (Later attempts complained about
not being able to access the index.)

So, in Ruby a private method is one that can only be called by the
object itself, and that's enforced by the simple rule of disallowing
an explicit receiver. Of course, there are ways around this; any
message can be passed if you just know what to do. Maybe I'm late to
the game, but I didn't realize it was okay to have #initialize be a
private method. More than that, I didn't realize #initialize was
*always* private. This confuses me because I think of SomeClass.new to
be

    def new(*args, &block)
      instance = allocate
      instance.initialize(*args, &block)
      instance
    end

But that obviously can't be the case if #initialize is private.
Instead, it has to be

    def new(*args, &block)
      instance = allocate
      instance.send(:initialize, *args, &block)
      instance
    end

It's a small change, but significant. And it seems odd to have
something this central to the language skirting the boundaries of
access control. Is it simply because an object shouldn't be re-
initialized once it's created? And if so, is that so horrible?
D83785463666ae9bb98a0753eebc8950?d=identicon&s=25 Wayne Vucenic (Guest)
on 2008-11-27 23:59
(Received via mailing list)
On Thu, Nov 27, 2008 at 12:38 PM, Yossef Mendelssohn <ymendel@pobox.com>
wrote:

> Is it simply because an object shouldn't be re-
> initialized once it's created? And if so, is that so horrible?

I don't think the issue is that an object shouldn't be re-initialized, I
think
it's that (in general) an object shouldn't be re-initialized by anyone
except itself.   If I'm writing a class, I'll declare certain instance
methods
private, because I don't want clients calling them.  initialize seems
like
a method that I rarely want clients to be able to call.

Best regards,

Wayne

---
Wayne Vucenic
No Bugs Software
Agile Ruby (but preferably not Rails) Contract Programming in Silicon
Valley since 2001
0ec4920185b657a03edf01fff96b4e9b?d=identicon&s=25 Yukihiro Matsumoto (Guest)
on 2008-11-28 00:38
(Received via mailing list)
Hi,

In message "Re: private #initialize"
    on Fri, 28 Nov 2008 05:38:47 +0900, Yossef Mendelssohn
<ymendel@pobox.com> writes:

|And it seems odd to have
|something this central to the language skirting the boundaries of
|access control. Is it simply because an object shouldn't be re-
|initialized once it's created? And if so, is that so horrible?

#initialize is, by its design, supposed to be called only from within
#new to separate per object/class initialization from the #new, thus
you don't have to redefine #new.  When you need/want to redefine #new,
it's a sign of a bad design, I believe.

One of the reason #initialize being private is to tell you bad design.

              matz.
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2008-11-28 02:30
(Received via mailing list)
On Fri, Nov 28, 2008 at 12:32 AM, Yukihiro Matsumoto
<matz@ruby-lang.org> wrote:

> #initialize is, by its design, supposed to be called only from within
> #new to separate per object/class initialization from the #new, thus
> you don't have to redefine #new.  When you need/want to redefine #new,
> it's a sign of a bad design, I believe.
I am delivering this code to your judgment

module Immutable
  def new *args, &blk
    o = allocate
    o.send( :initialize, *args, &blk )
    o.freeze
  end
end

>
> One of the reason #initialize being private is to tell you bad design.

I can not come up with a better design as the above. But I am
listening of course.
Calling freeze on self at the end of #initialize is really asking for
trouble with subclasses.

Now that all said, it is good that #initialize is private because it
makes you think before doing tricky things as above
but I would not call it bad design.

Cheers
Robert

--
Ne baisse jamais la tête, tu ne verrais plus les étoiles.

Robert Dober ;)
0ec4920185b657a03edf01fff96b4e9b?d=identicon&s=25 Yukihiro Matsumoto (Guest)
on 2008-11-28 09:09
(Received via mailing list)
Hi,

In message "Re: private #initialize"
    on Fri, 28 Nov 2008 10:24:24 +0900, "Robert Dober"
<robert.dober@gmail.com> writes:

|On Fri, Nov 28, 2008 at 12:32 AM, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:
|
|> #initialize is, by its design, supposed to be called only from within
|> #new to separate per object/class initialization from the #new, thus
|> you don't have to redefine #new.  When you need/want to redefine #new,
|> it's a sign of a bad design, I believe.
|I am delivering this code to your judgment
|
|module Immutable
|  def new *args, &blk
|    o = allocate
|    o.send( :initialize, *args, &blk )
|    o.freeze
|  end
|end

It's far better than normal #new replacement.  But it's still not
worth making #initialize public though.  Honestly speaking, tasks like
the code you've presented should be solved by AOP or method
combination, which unfortunately Ruby does not have right now.
Maybe in the future.

              matz.
Baf83fa62a7481a08c40353795e11f44?d=identicon&s=25 Michael Neumann (Guest)
on 2008-11-28 09:56
(Received via mailing list)
Robert Dober schrieb:
>     o = allocate
>     o.send( :initialize, *args, &blk )
>     o.freeze
>   end
> end

How about this?

module Immutable
   def new(*args, &blk)
     super.freeze
   end
end

Okay, this will not work if you redefine #new yourself. Or that?

module Immutable
   def self.included(klass)
     class << klass
       alias __old_new new
       def new(*args, &blk)
         __old_new(*args, &blk).freeze
       end
     end
   end
end

(will not work when including into a module)

Regards,

   Michael
Cf7cd97cdc8ed7d4ae92965b24f0dfad?d=identicon&s=25 Stefan Rusterholz (apeiros)
on 2008-11-28 13:16
Michael Neumann wrote:
> How about this?
> module Immutable
>    def self.included(klass)
>      class << klass
>        alias __old_new new
>        def new(*args, &blk)
>          __old_new(*args, &blk).freeze
>        end
>      end
>    end
> end

Wrong hook. new is a class method, so you'll want to extend, so def
self.extended.

Regards
Stefan Rusterholz
This topic is locked and can not be replied to.