Why this behaves like singleton

The attached code prints:

print g1 locks
5
print g2 locks
5
3

I would expect g2 to print 3. Why the Lock object behaves
like singleton?

Thanks.

Javier.

Hi,

a class variable (in your case @@locks) is shared among the class and
all instances of the class – as well as all subclasses and their
instances. So when g1 or g2 do something with @@locks, it’s always the
same array.

I think you generally misunderstand the difference between the various
types of variables. For example, the variable @lock in @lock = 0 is
completely different from the one you use in the initialize method, and
in your case it’s simply useless. Ruby is not Java where this syntax is
used to set default values.

So you might wanna read up on this topic:
http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Classes

You should generally avoid class variables unless you really know what
you’re doing. Use instance variables or class instance variables
depending on the specific purpose.

To fix your code, replace @@locks with an instance variable and set it
in the correct context:


class Locks
def initialize ( rd )
@locks = []
rd.each do |k|
@locks << Lock.new(rd)
end
end

def printLocks
@locks.each do |l|
puts l.glock()
end
end
end

On Tue, Nov 27, 2012 at 5:00 PM, Javier I. [email protected]
wrote:

like singleton?
class Lock
@lock = 0

This variable is not the same as the one used below in initialize

and glock methods. The reason is that @xxx refers to an instance
variable of the object that happens to be self in that scope, and in
this case the object is the Lock class itself, while in the initialize
and glock methods, it’s a specific instance of the Lock class. So, in
summary, you can remove this line.

def initialize(r)
@lock = r
end
def glock()
@lock
end
end

class Locks
@@locks = []

A variable prefixed with @@ is a class variable. It is shared among

the class and all its subclasses. Every reference to this variable in
this scope or in instance methods of this class or any subclass will
refer to the same object. You most certainly don’t want this. So
remove this and change it with @locks = [] inside the initialize
method, which creates an instance variable of the object being
initialized.

def initialize ( rd )
rd.each do |k|
@@locks << Lock.new(rd)
end
end

def printLocks
@@locks.each do |l|
puts l.glock()
end
end
end

I would try:

class Lock
attr_reader :lock
def initialize r
@lock = r
end
end

class Locks
def initialize lock_ids
@locks = []
lock_ids.each {|id| @locks << Lock.new(id)}
end

def print_locks
@locks.each {|lock| puts lock.lock}
end
end

1.9.2p290 :019 > g1 = Locks.new([5])
=> #<Locks:0x00000001744568 @locks=[#<Lock:0x00000001744518 @lock=5>]>
1.9.2p290 :020 > puts “print g1 locks”
print g1 locks
=> nil
1.9.2p290 :021 > g1.print_locks
5
=> [#<Lock:0x00000001744518 @lock=5>]
1.9.2p290 :022 > g2 = Locks.new([3])
=> #<Locks:0x0000000174fc38 @locks=[#<Lock:0x0000000174fbe8 @lock=3>]>
1.9.2p290 :023 > puts “print g2 locks”
print g2 locks
=> nil
1.9.2p290 :024 > g2.print_locks
3

Jesus.