Class Initialization?

I have a class and two class methods: self.encode and self.decode. The
encode method expects a class variable (@@table) to be “initialized”.
Whereas it’s possible to do that in def self.encode(bytes) method of my
class, I was interested to know if I can do that elsewhere (static
blocks, a la Java?). What is the recommended way to do such class
initialization tasks?

-Kedar

On Wed, Jan 5, 2011 at 3:33 PM, Kedar M.
[email protected] wrote:

I have a class and two class methods: self.encode and self.decode. The
encode method expects a class variable (@@table) to be “initialized”.
Whereas it’s possible to do that in def self.encode(bytes) method of my
class, I was interested to know if I can do that elsewhere (static
blocks, a la Java?). What is the recommended way to do such class
initialization tasks?

The class body is essentially what a static block is in a Java class:
it is executed at “class load time” which in Ruby is “class definition
time”.

15:37:59 $ ruby19 <<CODE

class Foo
@bar = “initialized”
def self.ok?() @bar end
end
p Foo.ok?
CODE
“initialized”
15:38:34 $

Note, please don’t use @@class_variables - they are just too awkward.
Using ordinary class members is totally sufficient.

Kind regards

robert

On Wed, Jan 5, 2011 at 9:33 AM, Kedar M.
[email protected]wrote:

If I’m understanding right, something like one of these should work:

class MyClass
@@table = 42;

def self.encode(bytes)
//…
end

def self.decode
//…
end
end

OR

class MyClass
def self.initialize_table
@@table = …
end

initialize_table

def self.encode(bytes)
//…
end

def self.decode
//…
end
end

Robert, Andrew,

Thank you.
It was not clear if the “class body” will be executed at most once.
That’s now clear.

I like this better than Java’s static initializer!

Robert – but isn’t @@x a class variable and @x an instance variable?
Maybe I am confused a bit. I want this “table” I am initializing to be
available from the class, without having to create any instances of it.

On Wed, Jan 5, 2011 at 12:18 PM, Kedar M.
[email protected]wrote:

available from the class, without having to create any instances of it.


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

To answer this, grasshopper, I suggest you study this code, and figure
out
how it works. Hint: there are more than one @count variables.

class Counter
@count = 0

class << self
attr_accessor :count
end

def initialize
self.class.count += 1
@count = self.class.count
end

def output
puts “I am counter object number #{@count} of #{self.class.count}”
end
end

x = Counter.new
x.output # I am counter object number 1 of 1

y = Counter.new
x.output # I am counter object number 1 of 2
y.output # I am counter object number 2 of 2

On Wed, Jan 5, 2011 at 6:18 PM, Kedar M.
[email protected] wrote:

It was not clear if the “class body” will be executed at most once.
That’s now clear.

Good!

I like this better than Java’s static initializer!

Robert – but isn’t @@x a class variable and @x an instance variable?
Maybe I am confused a bit. I want this “table” I am initializing to be
available from the class, without having to create any instances of it.

Short answer: classes can have instance variables as well. Long
answer (please see Andrew’s reply). Variables with @@ are really a
hybrid which is directly readable from the class and instance. But
there are some subtle issues with order in which they are created and
so I always recommend to not use them. You’ll find plenty of
discussions of this in the archives.

Kind regards

robert

Kedar M. wrote in post #972556:

It was not clear if the “class body” will be executed at most once.
That’s now clear.

And indeed, the execution of the code is what defines the class. The
class and methods are defined at runtime.

Foo.bar rescue nil # uninitialized constant Foo
class Foo
def self.bar
puts “hello!”
end
end
Foo.bar # this works

Amongst other things, this means you can conditionally define classes
and methods.

However the code will be executed multiple times if you force it to be -
for example using ‘load’ instead of ‘require’. This can also happen if
you require the same file using variations of the name, e.g.

require ‘foo’
require ‘./foo’
require ‘/path/to/foo’

Andrew W. wrote in post #972567:

On Wed, Jan 5, 2011 at 12:18 PM, Kedar M.
[email protected]wrote:

available from the class, without having to create any instances of it.


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

To answer this, grasshopper, I suggest you study this code, and figure
out
how it works. Hint: there are more than one @count variables.

class Counter
@count = 0

class << self
attr_accessor :count
end

def initialize
self.class.count += 1
@count = self.class.count
end

def output
puts “I am counter object number #{@count} of #{self.class.count}”
end
end

x = Counter.new
x.output # I am counter object number 1 of 1

y = Counter.new
x.output # I am counter object number 1 of 2
y.output # I am counter object number 2 of 2

My n00b parser is stuck at class << self for I have to yet learn that
construct, I guess.

But I will spend more time understanding this example. My first attempt
tells me that there are two types of variables (one: class, other
instance) and both are named count.

I am still influenced by the “initially straightforward” example given
in the Pickaxe book that counts the number of Song objects created thus
far (i.e. incrementing @@count by 1 in the initialize method).

Thank you.

Brian C. wrote in post #972835:

Kedar M. wrote in post #972556:

It was not clear if the “class body” will be executed at most once.
That’s now clear.

And indeed, the execution of the code is what defines the class. The
class and methods are defined at runtime.

Foo.bar rescue nil # uninitialized constant Foo
class Foo
def self.bar
puts “hello!”
end
end
Foo.bar # this works

Amongst other things, this means you can conditionally define classes
and methods.

However the code will be executed multiple times if you force it to be -
for example using ‘load’ instead of ‘require’. This can also happen if
you require the same file using variations of the name, e.g.

require ‘foo’
require ‘./foo’
require ‘/path/to/foo’

Brian,

Interesting. So, the initialization is that of a file and not a class? I
thought no matter how some ruby code “requires” a class defined
elsewhere, the class initialization will be done at most once.

Thanks for the hint.

-Kedar

On Thu, Jan 6, 2011 at 2:41 PM, Kedar M.
[email protected]wrote:

To answer this, grasshopper, I suggest you study this code, and figure
def initialize
x.output # I am counter object number 1 of 1
instance) and both are named count.

Well, there are two variables, on two different objects (the class and
its
instance), but the point is that they’re not two different types. They
work the same way, they’re just on two different objects.

Here’s a snipped that avoids the mean “class <<” stuff (with my
apologies
for my laziness):

class Counter
@count = 0

def self.count
@count
end

def self.count=(val)
@count = val
end

def initialize
self.class.count += 1
@count = self.class.count
end

def output
puts “I am counter object number #{@count} of #{self.class.count}”
end
end

x = Counter.new
x.output # I am counter object number 1 of 1

y = Counter.new
x.output # I am counter object number 1 of 2
y.output # I am counter object number 2 of 2

I am still influenced by the “initially straightforward” example given

Robert K. wrote in post #972742:

On Wed, Jan 5, 2011 at 6:18 PM, Kedar M.
[email protected] wrote:

It was not clear if the “class body” will be executed at most once.
That’s now clear.

Good!

I like this better than Java’s static initializer!

Robert – but isn’t @@x a class variable and @x an instance variable?
Maybe I am confused a bit. I want this “table” I am initializing to be
available from the class, without having to create any instances of it.

Short answer: classes can have instance variables as well. Long
answer (please see Andrew’s reply). Variables with @@ are really a
hybrid which is directly readable from the class and instance. But
there are some subtle issues with order in which they are created and
so I always recommend to not use them. You’ll find plenty of
discussions of this in the archives.

Perhaps these are the Ruby Pro techniques. I think I have to read more
and experiment more to understand them better.

Thank you.

On Jan 6, 2011, at 3:06 PM, Kedar M. wrote:

And in the process of explaining this, you also indirectly explained one
question that was lurking in my mind – are the
attr_readers/writers/accessors available to class variables – and as I
understand it, they are – by way of your previous class << self
construct.

Careful here. The attr* methods are manipulating instance variables and
not class variables.

instance variables: private to an object
class instance variables: instance variables for an object that
just happens to be a class
class variables: nasty, confusing things that have the same name
but not at all the same semantics as ‘class
variables’ in other languages

I think it is very unfortunate that a lot of introductory Ruby texts
choose
to emphasize class variables (@@foo) over plain old instance variables
of
a class (@foo for a class object).

If there were one feature I would remove from Ruby (maybe in Ruby 2.0?)
it
would be class variables.

Gary W.

On Thu, Jan 6, 2011 at 10:43 PM, Gary W. [email protected] wrote:

not class variables.
to emphasize class variables (@@foo) over plain old instance variables of
a class (@foo for a class object).

Completely agree.

If there were one feature I would remove from Ruby (maybe in Ruby 2.0?) it
would be class variables.

+2

We could start by flagging usage of class variables with a warning -
at least with option -w set.

Kind regards

robert

Andrew W. wrote in post #972912:

On Thu, Jan 6, 2011 at 2:41 PM, Kedar M.
[email protected]wrote:

To answer this, grasshopper, I suggest you study this code, and figure
def initialize
x.output # I am counter object number 1 of 1
instance) and both are named count.

Well, there are two variables, on two different objects (the class and
its
instance), but the point is that they’re not two different types. They
work the same way, they’re just on two different objects.

Here’s a snipped that avoids the mean “class <<” stuff (with my
apologies
for my laziness):

class Counter
@count = 0

def self.count
@count
end

def self.count=(val)
@count = val
end

def initialize
self.class.count += 1
@count = self.class.count
end

def output
puts “I am counter object number #{@count} of #{self.class.count}”
end
end

x = Counter.new
x.output # I am counter object number 1 of 1

y = Counter.new
x.output # I am counter object number 1 of 2
y.output # I am counter object number 2 of 2

Andrew!

Thank you. This makes it very clear. This particular arrangement makes
clever use of instance variable. One is on the class instance and the
other is on the each instance of that class.

And in the process of explaining this, you also indirectly explained one
question that was lurking in my mind – are the
attr_readers/writers/accessors available to class variables – and as I
understand it, they are – by way of your previous class << self
construct.

Now I can safely ignore any discussion on @@ variables in any book :wink:

Thanks!
-Kedar