Class attribute unique to subclasses but used in parent class

Discussion in 'Ruby' started by lcor1979@gmail.com, Oct 28, 2006.

  1. Guest

    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
    , Oct 28, 2006
    #1
    1. Advertising

  2. Guest

    Hi --

    On Sat, 28 Oct 2006, wrote:

    > 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 |
    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
    , Oct 28, 2006
    #2
    1. Advertising

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

    wrote:
    > 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--
    David Vallner, Oct 28, 2006
    #3
  4. Guest

    Hi --

    On Sun, 29 Oct 2006, David Vallner wrote:

    > wrote:
    >> 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.
    >>

    >
    > 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 |
    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
    , Oct 28, 2006
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bostonasian
    Replies:
    1
    Views:
    806
    Joris Gillis
    Sep 18, 2005
  2. Thomas Heller
    Replies:
    1
    Views:
    304
    Michael Hudson
    Aug 20, 2004
  3. ToshiBoy
    Replies:
    6
    Views:
    828
    ToshiBoy
    Aug 12, 2008
  4. Token Type
    Replies:
    9
    Views:
    339
    Chris Angelico
    Sep 9, 2012
  5. Bitswapper
    Replies:
    5
    Views:
    116
    Prasad, Ramit
    Aug 27, 2013
Loading...

Share This Page