Class Initialization?

K

Kedar Mhaswade

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
 
R

Robert Klemme

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
 
A

Andrew Wagner

[Note: parts of this message were removed to make it a legal post.]

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

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
 
K

Kedar Mhaswade

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.
 
A

Andrew Wagner

[Note: parts of this message were removed to make it a legal post.]

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.
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
 
R

Robert Klemme

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
 
B

Brian Candler

Kedar Mhaswade 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'
 
K

Kedar Mhaswade

Andrew Wagner wrote in post #972567:
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.
 
K

Kedar Mhaswade

Robert Klemme wrote in post #972742:
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.
 
K

Kedar Mhaswade

Brian Candler wrote in post #972835:
Kedar Mhaswade wrote in post #972556:

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
 
A

Andrew Wagner

[Note: parts of this message were removed to make it a legal post.]

Andrew Wagner wrote in post #972567:

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.
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
 
K

Kedar Mhaswade

Andrew Wagner wrote in post #972912:
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 ;)

Thanks!
-Kedar
 
G

Gary Wright

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 Wright
 
R

Robert Klemme

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

instance variables: =A0 =A0 =A0 =A0private to an object
class instance variables: =A0instance variables for an object that
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 just happens to be a = class
class variables: =A0 =A0 =A0 =A0 =A0 nasty, confusing things that have th= e same name
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 but not at all the sa= me semantics as 'class
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 variables' in other l= anguages


I think it is very unfortunate that a lot of introductory Ruby texts choo= se
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?) i= t
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

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 

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,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top