(Static) Constructors/Destructors in Ruby

Hello!

After reading the Pickaxe book I noticed it provides almost no
information about object lifecycle and no mention of destructors. As a
Java/C# guy my gut reaction was: Wouldn’t it be nice to have a
“unintialize” method to be called when the object is being destroyed?

There seems to be some form of destructor (called finalizers) in the
ObjectSpace module, but it seems to be an afterthought rather that an
integral feature of the language.

Another thing I find very surprising for a language having such a rich
OO model is the lack of static constructors (available in C# and somehow
in Java) and static destructors (something I always wanted to have in
Java/C#).

Based on that I will appreciate your thoughts on why a language having
such advanced OO features is lacking in these areas and is there any way
to emulate these.

Thanks

···

--
Posted via http://www.ruby-forum.com/.

PrimaryKey wrote:

Hello!

After reading the Pickaxe book I noticed it provides almost no
information about object lifecycle and no mention of destructors. As a
Java/C# guy my gut reaction was: Wouldn’t it be nice to have a
“unintialize” method to be called when the object is being destroyed?

Java does not have destructors either. finalize method is not guaranteed to be called

Another thing I find very surprising for a language having such a rich
OO model is the lack of static constructors (available in C# and somehow
in Java) and static destructors (something I always wanted to have in
Java/C#).

Ruby has them. Every class definition is an executable code (public, private, protected are methods) so you can alternate method definitions with arbitrary code (in fact, this is much more powerful mechanism than static blocks in Java and static constructors in C#)

lopex

PrimaryKey wrote:

Hello!

After reading the Pickaxe book I noticed it provides almost no
information about object lifecycle and no mention of destructors. As a
Java/C# guy my gut reaction was: Wouldn't it be nice to have a
"unintialize" method to be called when the object is being destroyed?

There seems to be some form of destructor (called finalizers) in the
ObjectSpace module, but it seems to be an afterthought rather that an
integral feature of the language.

Not so much an afterthought as discouraged.

Here's a good discussion about Ruby's finalizers:

PrimaryKey wrote:

There seems to be some form of destructor (called finalizers) in the
ObjectSpace module, but it seems to be an afterthought rather that an
integral feature of the language.

Actually, it is a very well thought out feature of the language. In
Java, the finalizer is run when the object is eligible for garbage
collection. But within the finalizer, you can create a new reference to
the object and make it ineligible for collection.

In Ruby, the finalizer is not run until *after* the object is collected.
Since the object itself is no longer around, there is no possibility of
even accidently creating a new reference to the object. It also means
that the finalizer can't be an instance method (because the instance is
gone when the finalizer is run).

Another thing I find very surprising for a language having such a rich
OO model is the lack of static constructors (available in C# and somehow
in Java) and static destructors (something I always wanted to have in
Java/C#).

How would you use static constructors/destructors? Perhaps we can show
you Ruby equivalents.

···

--
-- Jim Weirich

--
Posted via http://www.ruby-forum.com/\.

Hi.

PrimaryKey wrote:

Based on that I will appreciate your thoughts on why a language having
such advanced OO features is lacking in these areas and is there any way
to emulate these.

Actually, destructor in Java, i.e., finalize( ), does not well behave.
Moreover, using it properly is next to impossible. Have a look at:

Here's the recap:
(1) Java finalizer is not guranteed to run.
(2) Java finalizer is not executed in the main thread. Instead, it runs
in its own thread. Hence, synchronization mechanism for read/write
visibility and concurrency control is required.
(3) If java finalizer access a certain object which is already garbage
collected, then the object will resurrect. To avoid this situation, you
should not access garbage collected object while finalizing, but it is
not easy because there's no certain order in garbage collection.

Instead of relying on finalize, you'd better use dispose pattern like:

class Foo
   def dispose
      # release all non-managed resources
   end
end

You can find similar interface, IDisposable, in C#. The reason is that
people developed C# already found that writing destructor for releasing
unmanaged resources is not simple than writing explicit dispose method.

Sincerely,
Minkoo Seo

A bit off-topic, but note,

  Oracle Java Technologies | Oracle

dave

···

On Sat, Apr 01, 2006 at 03:25:23AM +0900, PrimaryKey wrote:

[...] static destructors (something I always wanted to have in
Java/C#).

--
http://david.holroyd.me.uk/

Does anyone know under what conditions the finalizer won't be called?

···

On 3/31/06, Marcin Mielżyński <lopexx@autograf.pl> wrote:

PrimaryKey wrote:
> Hello!
>
> After reading the Pickaxe book I noticed it provides almost no
> information about object lifecycle and no mention of destructors. As a
> Java/C# guy my gut reaction was: Wouldn't it be nice to have a
> "unintialize" method to be called when the object is being destroyed?
>

Java does not have destructors either. finalize method is not guaranteed
to be called

> Another thing I find very surprising for a language having such a rich
> OO model is the lack of static constructors (available in C# and somehow
> in Java) and static destructors (something I always wanted to have in
> Java/C#).

Ruby has them. Every class definition is an executable code (public,
private, protected are methods) so you can alternate method definitions
with arbitrary code (in fact, this is much more powerful mechanism than
static blocks in Java and static constructors in C#)

lopex

--
-Dan Nugent

Don't Feel Like Typing? Send me a voicemail:

How would you use static constructors/destructors? Perhaps we can show
you Ruby equivalents.

--
-- Jim Weirich

Please consider the following (pseudo) C# example:

  public class AS400Server
  {
    static AS400 server;

    static AS400Server()
    {
      server = new AS400Connection("SERVERNAME");
    }

    static ~AS400Server() // This is not real C#
    {
      server.disconnect();
    }

    static int GetServer()
    {
      return server;
    }
  }

I know this probably can be emulated using a singleton, I still believe
having static destructors will be nice because:

1. I like the constructor/destructor symmetry in C++
2. It can be helpful for meta-programming purposes. My impression is
most languages try to implement the traditional OO tools on class
(static) level

Thanks

···

--
Posted via http://www.ruby-forum.com/\.

Jim Weirich wrote:

In Ruby, the finalizer is not run until *after* the object is collected. Since the object itself is no longer around, there is no possibility of even accidently creating a new reference to the object. It also means that the finalizer can't be an instance method (because the instance is gone when the finalizer is run).

This makes perfect sense since Ruby uses mark&sweep. But in Python is it possible to supply __del__ method which seems to be an instance one (correct me if I'm wrong), but the moment of GC cannot be determined anyways. And as rmagick mentioned, explicit destrutors are not needed anyways.

lopex

class AS400Server
      @server = AS400Connection.new
      def self.get_server
             @server
       end
  end

As for a static deconstructor, can't really help you, I don't think classes are really ever GCed until the very end, anyway. however, you could do this:

class AS400Server
      at_exit { @server.disconnect }
end

···

On Mar 31, 2006, at 2:58 PM, PrimaryKey wrote:

How would you use static constructors/destructors? Perhaps we can show
you Ruby equivalents.

--
-- Jim Weirich

Please consider the following (pseudo) C# example:

  public class AS400Server
  {
    static AS400 server;

    static AS400Server()
    {
      server = new AS400Connection("SERVERNAME");
    }

    static ~AS400Server() // This is not real C#
    {
      server.disconnect();
    }

    static int GetServer()
    {
      return server;
    }
  }

I know this probably can be emulated using a singleton, I still believe
having static destructors will be nice because:

1. I like the constructor/destructor symmetry in C++
2. It can be helpful for meta-programming purposes. My impression is
most languages try to implement the traditional OO tools on class
(static) level

Thanks

--
Posted via http://www.ruby-forum.com/\.

I believe this is the case if the garbage collector never runs. That is, if the program exits before it is necessary.
Also, there are situations in which objects are never released, so the finalize method won't be called then, either. If I recall correctly.

-Justin

Daniel Nugent wrote:

···

Does anyone know under what conditions the finalizer won't be called?

On 3/31/06, Marcin Mielżyński <lopexx@autograf.pl> wrote:
  

PrimaryKey wrote:
    

Hello!

After reading the Pickaxe book I noticed it provides almost no
information about object lifecycle and no mention of destructors. As a
Java/C# guy my gut reaction was: Wouldn't it be nice to have a
"unintialize" method to be called when the object is being destroyed?

Java does not have destructors either. finalize method is not guaranteed
to be called

Another thing I find very surprising for a language having such a rich
OO model is the lack of static constructors (available in C# and somehow
in Java) and static destructors (something I always wanted to have in
Java/C#).
      

Ruby has them. Every class definition is an executable code (public,
private, protected are methods) so you can alternate method definitions
with arbitrary code (in fact, this is much more powerful mechanism than
static blocks in Java and static constructors in C#)

lopex

--
-Dan Nugent

Don't Feel Like Typing? Send me a voicemail:
W77 🏀 The Best Site for Providing Big Wins in a Fruit Spin Game

PrimaryKey wrote:

How would you use static constructors/destructors? Perhaps we can show
you Ruby equivalents.

--
-- Jim Weirich

Please consider the following (pseudo) C# example:

  public class AS400Server
  {
    static AS400 server;

    static AS400Server()
    {
      server = new AS400Connection("SERVERNAME");
    }

    static ~AS400Server() // This is not real C#
    {
      server.disconnect();
    }

    static int GetServer()
    {
      return server;
    }
  }

I would ask first: does having one class per connection ("SERVERAME")
scale well? what if you need two servers...? This question isn't really
off topic, because once you accept this possibility, it becomes very
natural in ruby to do this:

class AS400Server
  def initialize(serv_name)
    @serv_name = serv_name
  end

  def connect
    # do something to connect to the server
    yield self
  ensure
    # do something to disconnet
  end
end

Then in your main code you might have:

def run_my_app
  AS400Server.new("SERVERNAME").connect do |serv|
    # do something with serv
  end
end

or

THE_SERVER = AS400Server.new("SERVERNAME")
def run_my_app
  THE_SERVER.connect do
    # do something with THE_SERVER
  end
end

Unless you exit with Kernel#exit! or the process is killed in a way that
ruby cannot catch (e.g., SIGKILL), the ensure clause will close the
server connection first. (Anyway, in the case of SIGKILL, a static
destructor would not be called either, right? Or can C# do that?)

(You can even roll the #connect method into initialize, if you want.
Passing the server object from yeild isn't really necessary, but you may
need to reference it in the block.)

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

PrimaryKey wrote:

Please consider the following (pseudo) C# example:

I think Logan Capaldo's answer is hits pretty close to your intention
here. However, I have to comment because I've been retrofitting unit
tests in to a legacy (Java) code base this past week and I've come to
*hate* static initializers.

The code base does something similar to your example and the code is
impossible to unit test without some restructuring. Since the database
connection is made in static initializers, I can't even load the class
without having the infrastructure for a database connection available.
Yuck!

I've come to consider complex static initializers (e.g. making DB
connections in the initilizer) a thing of "evil".

Ok, rant over. :wink:

[...]
2. It can be helpful for meta-programming purposes. My impression is
most languages try to implement the traditional OO tools on class
(static) level

I'm not getting statement #2 above.

Thanks.

···

--
-- Jim Weirich

--
Posted via http://www.ruby-forum.com/\.

Please consider the following (pseudo) C# example:

  public class AS400Server
  {
    static AS400 server;

    static AS400Server()
    {
      server = new AS400Connection("SERVERNAME");
    }

    static ~AS400Server() // This is not real C#
    {
      server.disconnect();
    }

    static int GetServer()
    {
      return server;
    }
  }

I know this probably can be emulated using a singleton,

The singleton design pattern certainly can do that, and is easily used in Ruby by including module "Singleton" (except for the destruction part - although I expect a finaliser could do that for you, but I've not used them myself).

When you started to talk about these, I thought you were after 'structors for a class, rather than an instance. These are, of course, very easy in Ruby, as a class is just an object like any other. In fact, you can have little factories that will pump out classes, if you want.

I still believe
having static destructors will be nice because:

1. I like the constructor/destructor symmetry in C++

Actually, I like the c++ destructors too. I'd say they are one of the very few things that I miss about it :slight_smile: I quite often made use of a "stack object". It's an object with no interface except for it's 'structors. You would declare them "on the stack" in c++ (ie, without using new), so they are local to a code block. They're really useful for doing setup within a code block and ensuring that teardown happens when you exit it. They seem like a DRY way to specify the use of a mode within a code block:

class StackObject
{
public:
  StackObject() {do_setup_code();}
  ~StackObject() {do_teardown_code();}

private:
  void do_setup_code();
  void do_teardown_code();
};

And to use...

{
  // Setup resource.
  StackObject stack_object;

  // Do stuff with the mode being setup by the stack object.

  // Tear down happens automatically at block exit.
}

However, a very similar idea is possible in Ruby, and can be achieved with passing code blocks...

def run_within_mode
  setup_code
  yield
ensure
  teardown_code
end

And to use:

# Here, the mode is not in use yet.
run_within_mode do
  # Anything here is happening with the mode! Hooray!
end
# And the mode's gone again.

As well as ensuring the resource is cleaned up, both of these approaches are exception safe too.

Cheers,
  Ben

···

On 31 Mar 2006, at 20:58, PrimaryKey wrote:

{
  // Setup resource.
  StackObject stack_object;
  // Do stuff with the mode being setup by the stack object.
  // Tear down happens automatically at block exit.
}

However, a very similar idea is possible in Ruby, and can be achieved
with passing code blocks...

def run_within_mode
  setup_code
  yield
ensure
  teardown_code
end

And to use:

# Here, the mode is not in use yet.
run_within_mode do
  # Anything here is happening with the mode! Hooray!
end
# And the mode's gone again.

As well as ensuring the resource is cleaned up, both of these
approaches are exception safe too.

I like block idea, but must say that blocks can't give full replacement for
C++'s RAII ideom:

C++:

{
  File f1,f2,f3;
  Socket s1,s2;
  Database d;
} //here all f1,f2,f3,s1,s2,d being closed

Ruby:

???

Cheers,
  Ben

Victor.

Jim Weirich wrote:

2. It can be helpful for meta-programming purposes. My impression is
most languages try to implement the traditional OO tools on class
(static) level

I'm not getting statement #2 above.

Please consider the evolution of the class-level language features:

1. C++ - static member variables
2. Java - static members and static initialization blocks
3. C# - static members and static constructors

I think there is a clear pattern of implementing more and more of the
object-level OO features on class (static) level. I believe the next
logical step will be a language support for static destructors. As far
as meta-progamming is concerned the static features will beef up the
class level in the object-class-metaclass triad. Again, this is just the
personal opinion of a "evil" legacy(Java) programmer :slight_smile:

Thanks again,
Primary Key

···

--
Posted via http://www.ruby-forum.com/\.

The finalizers will be run on exit

    ObjectSpace.define_finalizer(a = "", lambda{ puts "EXECUTED" })
    END{ puts "leaving" }
    puts "hi"
    RUBY_VERSION # => "1.8.4"
    # >> hi
    # >> leaving
    # >> EXECUTED

But you can bypass them with Kernel#exit!

    batsman@tux-chan:~/mess/current$ cat exit_bang.rb
    ObjectSpace.define_finalizer(a = "", lambda{ puts "EXECUTED" })
    END{ puts "leaving" }
    puts "hi"
    puts RUBY_VERSION
    exit!
    batsman@tux-chan:~/mess/current$ ruby exit_bang.rb
    hi
    1.8.4

···

On Sat, Apr 01, 2006 at 06:31:42AM +0900, Justin Collins wrote:

I believe this is the case if the garbage collector never runs. That is,
if the program exits before it is necessary.
Also, there are situations in which objects are never released, so the
finalize method won't be called then, either. If I recall correctly.

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby

:slight_smile: It's such a fresh beautiful day outside... and here I am talking tech, when spring is springing :slight_smile:

Ok, in Ruby, each of those resources could easily be turned in to a method that will run a block. What you want to be able to do then, is easily compose those methods in to one, and have that run something within the context of resources being available?

Something along the lines of (unchecked code warning!)...?

def run_with_resources(*resources, &block)
  if resources ==
    yield
  else
    send(resources.slice(0)) {run_with_resources(*resources, &block)}
  end
end

You can then do...

run_with_resources(:file_handle, :db_connection, :socket_and_things, :other_groovy_bits) do
  #Wooo - look at all these resources!
end

It wouldn't be a big extension to collect up the resources passed in, and pop them in a map, or something. I don't think it would be hard to give the resources arguments either.

Cheers,
  Ben

···

On 1 Apr 2006, at 11:10, Victor Shepelev wrote:

I like block idea, but must say that blocks can't give full replacement for
C++'s RAII ideom:

C++:

{
  File f1,f2,f3;
  Socket s1,s2;
  Database d;
} //here all f1,f2,f3,s1,s2,d being closed

Ruby:

???

Primary Key wrote:

Jim Weirich wrote:

2. It can be helpful for meta-programming purposes. My impression is
most languages try to implement the traditional OO tools on class
(static) level

I'm not getting statement #2 above.

Please consider the evolution of the class-level language features:

1. C++ - static member variables
2. Java - static members and static initialization blocks
3. C# - static members and static constructors

I think there is a clear pattern of implementing more and more of the
object-level OO features on class (static) level.

Ok, at least for C-style languages I won't argue the point (although I'm
not entirely clear what a static constructor is ... other than a factory
function).

[...] As far
as meta-progamming is concerned the static features will beef up the
class level in the object-class-metaclass triad.

I'm still unclear on how static methods do anything to support
meta-progarmming. Perhaps an example might prove illuminating.

···

--
-- Jim Weirich

--
Posted via http://www.ruby-forum.com/\.

To clarify, I was talking about Java.

-Justin

···

-----Original Message-----
From: Mauricio Julio Fernández Pradier on behalf of Mauricio Fernandez
Sent: Sun 4/2/2006 4:31 AM
To: ruby-talk ML
Subject: Re: (Static) Constructors/Destructors in Ruby

On Sat, Apr 01, 2006 at 06:31:42AM +0900, Justin Collins wrote:

I believe this is the case if the garbage collector never runs. That is,
if the program exits before it is necessary.
Also, there are situations in which objects are never released, so the
finalize method won't be called then, either. If I recall correctly.

The finalizers will be run on exit

    ObjectSpace.define_finalizer(a = "", lambda{ puts "EXECUTED" })
    END{ puts "leaving" }
    puts "hi"
    RUBY_VERSION # => "1.8.4"
    # >> hi
    # >> leaving
    # >> EXECUTED

But you can bypass them with Kernel#exit!

    batsman@tux-chan:~/mess/current$ cat exit_bang.rb
    ObjectSpace.define_finalizer(a = "", lambda{ puts "EXECUTED" })
    END{ puts "leaving" }
    puts "hi"
    puts RUBY_VERSION
    exit!
    batsman@tux-chan:~/mess/current$ ruby exit_bang.rb
    hi
    1.8.4

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby