Class attribute unique to subclasses but used in parent class

L

lcor1979

Hello,

I'm new in the Ruby World and I have a question.

Let's say I have a class with a class attribute (I call this class
Parent), this class attribute is used in instance methods of Parent.
Parent class has many subsclasses. Each subsclass should have it's own
value of the class attribute.

Example:

class Parent
@@test = nil

def Parent.create(value)
@@test=value
new
end

def print_test
puts @@test
end
end

class Child1 < Parent
end

class Child2 < Parent
end

c1 = Parent.create '1'
c1.print_test # => 1
c2 = Parent.create '2'
c2.print_test # => 2
c1.print_test # => 2


What I'll like, is that Child1 and Child2 have their own values of
@@test, but @@test should be initialized and used in Parent.
Also, @@test cannot be an instance variable because it is heavy to
initialize and will be common to all instances of Child1 or Child2.

Thank you
 
D

dblack

Hi --

Hello,

I'm new in the Ruby World and I have a question.

Let's say I have a class with a class attribute (I call this class
Parent), this class attribute is used in instance methods of Parent.
Parent class has many subsclasses. Each subsclass should have it's own
value of the class attribute.

Example:

class Parent
@@test = nil

def Parent.create(value)
@@test=value
new
end

def print_test
puts @@test
end
end

class Child1 < Parent
end

class Child2 < Parent
end

c1 = Parent.create '1'
c1.print_test # => 1
c2 = Parent.create '2'
c2.print_test # => 2
c1.print_test # => 2


What I'll like, is that Child1 and Child2 have their own values of
@@test, but @@test should be initialized and used in Parent.
Also, @@test cannot be an instance variable because it is heavy to
initialize and will be common to all instances of Child1 or Child2.

Actually it should be an instance variable, but an instance variable
of the class object.

What you're trying to do is to maintain state on a per-object basis,
and for that you need an instance variable. In fact, you can give
your class objects their own accessor methods, by creating those
methods in the singleton class of the first one:

class C
class << self
attr_accessor :n
end
end

class D < C
end

C.n = 1
p C.n # 1
D.n = 2
p D.n # 2
p C.n # 1

Note that if you do this, you have to use the accessor methods to get
at the values from outside (as is the case with all objects):

class C
def my_class_n
self.class.n
end
end

c = C.new
C.n = 100
puts c.my_class_n # 100

But that's actually good. Since the object (C) is maintaining its own
state, it makes perfect sense to have to query it. Class variables
demolish that logic, which is one of a number of reasons I dislike
them.


David

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
D

David Vallner

--------------enig821922CDE8F98FA062F0B73E
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

What I'll like, is that Child1 and Child2 have their own values of
@@test, but @@test should be initialized and used in Parent.
Also, @@test cannot be an instance variable because it is heavy to
initialize and will be common to all instances of Child1 or Child2.
=20

Class variables and class instance variables sound way too much like
global state coming into the system through a backdoor, I'd avoid both.

Personally, I'd replace lookup through a class variable or class
instance variable with injecting the shared object into instances. The
less shared state, the more flexibility you gain in being able to rewire
your objects.

Disclaimer: I am biased in favour of IoC and DI based "objects floating
in vacuum" designs, especially for scenarios that involve reusing an
expensive-to-create component like this one. If nothing else,
declarative dependency resolution lets you plug in testing components
easier / clearer than imperative (even if Ruby makes the latter easier
in that you're allowed to molest any object in arbitrary ways.)

David Vallner


--------------enig821922CDE8F98FA062F0B73E
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (MingW32)

iD8DBQFFQ4DPy6MhrS8astoRAiJnAJ9CMYCCSLy+kvdYzNm29y2Yaxvi3gCdEQt+
4shucofN8bArAIbkQr7tiFM=
=BieB
-----END PGP SIGNATURE-----

--------------enig821922CDE8F98FA062F0B73E--
 
D

dblack

Hi --

Class variables and class instance variables sound way too much like
global state coming into the system through a backdoor, I'd avoid both.

Personally, I'd replace lookup through a class variable or class
instance variable with injecting the shared object into instances. The
less shared state, the more flexibility you gain in being able to rewire
your objects.

Instance variables don't involve shared state, though; they're
strictly per object (Class object or otherwise).


David

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 

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,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top