Professional Web Applications Themes

Class variables - a surprising result - Ruby

On Thu, Aug 21, 2003 at 06:33:09PM +0900, Jason Williams wrote: > class Sup > x = "A" > def test > print x > end > end > > class Sub1 < Sup > x = "B" > end > > class Sub2 < Sup > x = "C" > end > > Sup.new.test > Sub1.new.test > Sub2.new.test > > > I expect this to print "ABC", and yet it prints "CCC". Why is this? Class variable allocation is per class scope, not per subclass scope. Sub1, Sub2 and Sup really do share their class variables. Now don't ask ...

  1. #1

    Default Re: Class variables - a surprising result

    On Thu, Aug 21, 2003 at 06:33:09PM +0900, Jason Williams wrote:
    > class Sup
    > x = "A"
    > def test
    > print x
    > end
    > end
    >
    > class Sub1 < Sup
    > x = "B"
    > end
    >
    > class Sub2 < Sup
    > x = "C"
    > end
    >
    > Sup.new.test
    > Sub1.new.test
    > Sub2.new.test
    >
    >
    > I expect this to print "ABC", and yet it prints "CCC". Why is this?
    Class variable allocation is per class scope, not per subclass scope.
    Sub1, Sub2 and Sup really do share their class variables. Now don't
    ask me for the "why exactly"...

    -Martin

    Martin Weber Guest

  2. #2

    Default Re: Class variables - a surprising result

    > Class variable allocation is per class scope, not per subclass scope.
    > Sub1, Sub2 and Sup really do share their class variables. Now don't
    > ask me for the "why exactly"...
    I was fooled by this as well. I don't know why I intuitively would
    think that a subclass would get its own scope, but I did. Having your
    own scope as a subclass would be a really neat addition, though. But
    perhaps a reason from Matz would shed light?

    / David


    David Heinemeier Hansson Guest

  3. #3

    Default Re: Class variables - a surprising result

    > class Sup
    > x = "A"
    > def test
    > print x
    > end
    > end
    >
    > class Sub1 < Sup
    > x = "B"
    > end
    >
    > class Sub2 < Sup
    > x = "C"
    > end
    >
    > Sup.new.test
    > Sub1.new.test
    > Sub2.new.test
    >
    >
    > I expect this to print "ABC", and yet it prints "CCC". Why is this?
    hwow - for the stupid (me):
    x seems to be the same thing for the whole inheritance-hierarchy (or
    whatever this thing is called)... but i thought every class has it's very
    own class-vars....
    i mean... what's the purpose of that? hmmm. i did never notice this. i guess
    it just seems so strange due to me not being familiar with it this way...
    and - am i right? - in java it would say ABC, wouldn't it?
    strange...

    patrick


    Patrick Zesar Guest

  4. #4

    Default Re: Class variables - a surprising result

    At 6:33 PM +0900 8/21/03, Jason Williams wrote:
    > class Sup
    > x = "A"
    > def test
    > print x
    > end
    > end
    >
    > class Sub1 < Sup
    > x = "B"
    > end
    >
    > class Sub2 < Sup
    > x = "C"
    > end
    >
    > Sup.new.test
    > Sub1.new.test
    > Sub2.new.test
    >
    >I expect this to print "ABC", and yet it prints "CCC".
    >Why is this?
    That's what I would expect to happen, although I am not sure
    I could give a good explanation as to why it is "obvious"
    that it should work that way.

    As to what exactly is happening, the assignments to x are
    not inside any method. The assignments are processed as they
    are read in, not in the order that '.new' (or any other method)
    is called on any of the classes. Perhaps the following will
    give you a better idea of why you ended up with 'CCC':

    # - - - - start
    class Sup
    x = "A"
    line = 0
    def Sup.Ctest
    line += 1
    x += x[0,1]
    print line, "-", x, "\n"
    end
    end

    Sup.Ctest # first test
    Sup.Ctest # second test

    class Sub1 < Sup # define subclass
    x = "B"
    end

    Sub1.Ctest # third test
    Sup.Ctest # fourth test
    # - - - - end

    This produces:
    1-AA
    2-AAA
    3-BB
    4-BBB

    I am not sure if that really helps you with the question
    you're asking, though. Note that since you are only using
    class variables for this example, we can simply use a class
    method. There is no need for creating any instances of
    either of these classes, as far as the class variables are
    concerned.

    To get back to why there would be only one x for a class
    and all it's subclasses, let me refer to a line from the
    "Programming Ruby" (pickaxe) book: "A class variable is
    shared among all objects of a class, and is also accessible
    to the class methods...".

    Any object which is an instance of 'Sub1' is also, by
    definition, an instance of 'Sup'. If a class variable is
    shared among *all* objects of class 'Sup', then the exact
    same variable must also be shared with the objects which
    happen to be from class 'Sub1'.

    --
    Garance Alistair Drosehn = [email]gadgilead.netel.rpi.edu[/email]
    Senior Systems Programmer or [email]gadfreebsd.org[/email]
    Rensselaer Polytechnic Institute or [email]drosihrpi.edu[/email]

    Garance A Drosihn Guest

  5. #5

    Default Re: Class variables - a surprising result

    class Sup
    x = "A"
    def test
    print x
    end
    end

    class Sub1 < Sup
    x = "B"
    end

    class Sub2 < Sup
    x = "C"
    end

    Sup.new.test
    Sub1.new.test
    Sub2.new.test
    >>> CCC
    I think I know whats going on.

    When a variable is first used, that is where it is
    declared. Unlike Java there is no separate
    declaration. If you like, declaration is automatic
    when the variable is first reference.

    So Sup is declared. Class variable x is referenced
    and associated with Sup.

    Sup1 is declared. x is referenced. x is not
    found in the current class, so super.x is
    referenced.
    x is found, and updated.

    Note thae x = "B" is part of the classes
    declaration, and so will always be invoked, and that
    the 'message' will be passed back to Sup, thus
    updating the value of x in Sup.

    Same thing happens all over again in Sup2.

    Here is the code to get the desired result.

    class Sup
    x = nil
    writer: x
    def initialize
    x = "A"
    end
    def test
    print x
    end
    end

    class Sub1 < Sup
    def initialize
    x = "B"
    end
    end

    class Sub2 < Sup
    def initialize
    x = "C"
    end
    end

    Sup.new.test
    Sub1.new.test
    Sub2.new.test
    >>> ABC
    However, things still don't work out right if we
    assign to variables first. Replace the last three
    lines with:

    s = Sup.new
    s1a = Sub1.new
    s1b = Sub1.new
    s2a = Sub2.new
    s2b = Sub2.new

    s.test
    s1a.test
    s1b.test
    s2a.test
    s2b.test
    >> CCC
    Is this suprising? Perhaps not, here is the
    equivalent Java code:

    class sup {
    static char x = 'A';
    void test() {
    System.out.print(x);
    }
    }

    class sup1 extends sup {
    { x = 'B'; }
    }

    class sup2 extends sup {
    { x = 'C'; }
    }
    >>> CCC
    The original scenario cannot be ted in Java
    because a class is loaded and initialised at first
    use, rather than at declaration.

    class sup {
    static char x;
    sup() {
    x = 'A';
    }
    void test() {
    System.out.print(x);
    }
    }

    class sup1 extends sup {
    static char x;
    sup1() {
    x = 'B';
    }
    void test() {
    System.out.print(x);
    }
    }

    class sup2 extends sup {
    static char x;
    sup2() {
    x = 'C';
    }
    void test() {
    System.out.print(x);
    }
    }

    I can't find any cleaner way to do this in Java.
    Remove either the duplicate declaration of x or test()
    and your back to the original problem.

    So whats the best approach in ruby? To keep a class
    hash that contains a value associated with each class?







    __________________________________________________ ______________________
    Want to chat instantly with your online friends? Get the FREE Yahoo!
    Messenger [url]http://uk.messenger./[/url]

    Ged Byrne Guest

  6. #6

    Default Re: Class variables - a surprising result

    On Thu, 21 Aug 2003 19:02:43 +0900, David Heinemeier Hansson
    <davidloudthinking.com> wrote (more or less):
    >> Class variable allocation is per class scope, not per subclass scope.
    >> Sub1, Sub2 and Sup really do share their class variables. Now don't
    >> ask me for the "why exactly"...
    >
    >I was fooled by this as well. I don't know why I intuitively would
    >think that a subclass would get its own scope, but I did. Having your
    >own scope as a subclass would be a really neat addition, though. But
    >perhaps a reason from Matz would shed light?
    A class-instance variable is one in which the scope is specific to a
    given (sub)class.

    Am I correct in dimly recalling that Ruby has support for
    class-instance variables?



    Cheers,
    Euan
    Gawnsoft: [url]http://www.gawnsoft.co.sr[/url]
    Symbian/Epoc wiki: [url]http://html.dnsalias.net:1122[/url]
    Smalltalk links (harvested from comp.lang.smalltalk) [url]http://html.dnsalias.net/gawnsoft/smalltalk[/url]
    Gawnsoft Guest

  7. #7

    Default Re: Class variables - a surprising result

    Try:

    class Sup
    x = "A"
    def Sup.x
    x
    end
    def test
    print self.class.x
    end
    end

    class Sub1 < Sup
    x = "B"
    end

    class Sub2 < Sup
    x = "C"
    end

    Sup.new.test
    Sub1.new.test
    Sub2.new.test

    Not the simplest but...

    /Robert



    Robert Feldt Guest

  8. #8

    Default Re: Class variables - a surprising result

    Obviously there's some confusion though Matz.
    In most languages (C++, Java, Delphi, etc.), class variables (static's)
    are scoped by the *class*, not the entire inheritance chain.
    It's just... different. Once people understand it, it's fine, bug I
    definitely don't think it's *obvious*.

    -----Original Message-----
    From: Yukihiro Matsumoto [mailto:matzruby-lang.org]
    Sent: Thursday, August 21, 2003 10:50 AM
    To: ruby-talk ML
    Subject: Re: Class variables - a surprising result


    Hi,

    In message "Re: Class variables - a surprising result"
    on 03/08/21, David Heinemeier Hansson <davidloudthinking.com>
    writes:

    |> Class variable allocation is per class scope, not per subclass scope.

    |> Sub1, Sub2 and Sup really do share their class variables. Now don't
    |> ask me for the "why exactly"...
    |
    |I was fooled by this as well. I don't know why I intuitively would
    |think that a subclass would get its own scope, but I did. Having your
    |own scope as a subclass would be a really neat addition, though. But
    |perhaps a reason from Matz would shed light?

    They are variables. If you can't update values, how they can be
    variables.

    class Sup
    x = "A" # declare x, set x as "A"
    def test
    print x
    end
    end

    class Sub1 < Sup
    x = "B" # set x as "B"
    end

    class Sub2 < Sup
    x = "C" # set x as "C"
    end

    Sup.new.test # print the value of x ("C")
    Sub1.new.test # ditto.
    Sub2.new.test # ditto.

    Class variables are like global variables whose scope is limited to the
    inheritance tree.

    matz.




    Bennett, Patrick Guest

  9. #9

    Default Re: Class variables - a surprising result

    Gawnsoft wrote:
    >A class-instance variable is one in which the scope is specific to a
    >given (sub)class.
    >
    >Am I correct in dimly recalling that Ruby has support for
    >class-instance variables?
    >
    You are correct. If you search the ruby-talk archives you'll find a
    discussion almost the same as this
    one. Bottom line was that you have to do something like this:

    class Foo
    def initialize
    class << Foo
    class_instance_var = 'c'
    end
    end

    def test
    class << Foo
    puts class_instance_var
    end
    end
    end

    class Bar < Foo
    def initialize
    class << Bar
    class_instance_var = 55
    end
    end

    def inc
    class << Bar
    class_instance_var += 1
    end
    end

    def test
    class << Bar
    puts class_instance_var
    end
    end
    end

    foo1 = Foo.new
    bar1 = Bar.new
    bar2 = Bar.new

    foo1.test
    bar1.test
    bar2.test

    bar1.inc

    bar1.test
    bar2.test

    This prints:

    c
    55
    55
    56
    56


    Dan Doel Guest

  10. #10

    Default Re: Class variables - a surprising result

    > I have run into this because I'm working on a loans
    > system, and each item needs a unique id, which I've allocated as an
    > error correcting code. This gives me 46000 items. But if I have to
    > use the same class variable to number my users uniquely as well as
    > the items they borrow, that uses up space in my limited range.
    Um, this screams "instance variables" to me...

    What does your class represent, a user or a loan?

    -Kurt

    Kurt M. Dresner Guest

  11. #11

    Default Re: Class variables - a surprising result

    Hi,

    In message "Re: Class variables - a surprising result"
    on 03/08/22, Hugh Sasse Staff Elec Eng <hgsdmu.ac.uk> writes:

    |It would be nice to have variables like global variables limited to
    |all instances of a class but not inherited, too.

    I think it can be done by self.class trick given by Robert Feldt in
    [ruby-talk:79783].

    matz.

    Yukihiro Matsumoto Guest

  12. #12

    Default Re: Class variables - a surprising result

    Hi,

    In message "Re: Class variables - a surprising result"
    on 03/08/22, "Bennett, Patrick" <Patrick.Bennettinin.com> writes:

    |In most languages (C++, Java, Delphi, etc.), class variables (static's)
    |are scoped by the *class*, not the entire inheritance chain.

    As far as I know, C++ and Java do not have class variables. They have
    static member variables, which can be either private, protected, or
    public. I know nothing about Delphi.

    matz.

    Yukihiro Matsumoto Guest

  13. #13

    Default Re: Class variables - a surprising result

    On Fri, Aug 22, 2003 at 03:47:33AM +0900, Yukihiro Matsumoto wrote:
    > Hi,
    >
    > In message "Re: Class variables - a surprising result"
    > on 03/08/22, "Bennett, Patrick" <Patrick.Bennettinin.com> writes:
    >
    > |In most languages (C++, Java, Delphi, etc.), class variables (static's)
    > |are scoped by the *class*, not the entire inheritance chain.
    >
    > As far as I know, C++ and Java do not have class variables. They have
    > static member variables,
    .. . . which are not inherited, which is why it is surprising to many
    that Ruby's variables are inherited.

    -Mark
    Mark J. Reed Guest

  14. #14

    Default Re: Class variables - a surprising result

    My point was that many programmar's mistake Ruby's 'class' variables as
    equivalent to static variables (I did).
    Obviously they're not, but I thought it was worth pointing out that it's
    a source of confusion for some [like myself] (until they learn or are
    told otherwise).
    The fact that there were several messages about it (and several
    mentioning they didn't know it worked that way [I didn't for one]) I
    think it says something about
    its confusing (or perhaps under-doented) nature.

    Since you designed the langusge, I'm sure you're not the slightest bit
    confused by it. So, I think you can be discounted when it comes to
    tallying the votes on Ruby confusion. ;)

    Cheers...

    -----Original Message-----
    From: Yukihiro Matsumoto [mailto:matzruby-lang.org]
    Sent: Thursday, August 21, 2003 1:48 PM
    To: ruby-talk ML
    Subject: Re: Class variables - a surprising result


    Hi,

    In message "Re: Class variables - a surprising result"
    on 03/08/22, "Bennett, Patrick" <Patrick.Bennettinin.com> writes:

    |In most languages (C++, Java, Delphi, etc.), class variables (static's)

    |are scoped by the *class*, not the entire inheritance chain.

    As far as I know, C++ and Java do not have class variables. They have
    static member variables, which can be either private, protected, or
    public. I know nothing about Delphi.

    matz.




    Bennett, Patrick Guest

  15. #15

    Default Re: Class variables - a surprising result

    ----- Original Message -----
    From: "Yukihiro Matsumoto" <matzruby-lang.org>
    To: "ruby-talk ML" <ruby-talkruby-lang.org>
    Sent: Thursday, August 21, 2003 1:47 PM
    Subject: Re: Class variables - a surprising result

    > Hi,
    >
    > In message "Re: Class variables - a surprising result"
    > on 03/08/22, "Bennett, Patrick" <Patrick.Bennettinin.com> writes:
    >
    > |In most languages (C++, Java, Delphi, etc.), class variables (static's)
    > |are scoped by the *class*, not the entire inheritance chain.
    >
    > As far as I know, C++ and Java do not have class variables. They have
    > static member variables, which can be either private, protected, or
    > public. I know nothing about Delphi.
    eyebrow.raise

    This is interesting, because I would have said, "Those are class
    variables, they just don't CALL them that."

    I learned OOP from Eiffel (Meyer's OOSC book) -- just the terminology
    and concepts, I never actually coded in Eiffel.

    Don't I recall hearing that Ruby's class variables are based on those
    of Smalltalk? (I don't know Smalltalk.)

    If so, maybe the confusion is just related to mildly differing
    flavors of OOP.

    For the record, I have always been confused by Ruby's class variables
    also, thinking that they should belong to the class and not the
    hierarchy.

    Hal






    Hal E. Fulton Guest

  16. #16

    Default Re: Class variables - a surprising result

    > > As far as I know, C++ and Java do not have class variables. They have
    > > static member variables,
    >
    > .. . . which are not inherited, which is why it is surprising to many
    > that Ruby's variables are inherited.

    What do you mean by "not inherited"... I'm sure you're correct, but I'm
    confused:

    C:\tmp>cat Sub.java

    class Base {
    static int B = 1;
    }

    public class Sub extends Base {
    public static void main(String[] args) {
    System.out.println("Sub.B = " + Sub.B);
    }
    }


    C:\tmp>javac Sub.java

    C:\tmp>java Sub

    Sub.B = 1


    Michael Campbell Guest

  17. #17

    Default Re: Class variables - a surprising result

    Hal E. Fulton <hal9000hypermetrics.com> skrev den Fri, 22 Aug 2003
    03:58:13 +0900:
    > For the record, I have always been confused by Ruby's class variables
    > also, thinking that they should belong to the class and not the
    > hierarchy.
    >
    FTR, I've also been bitten by this. For me I think the problem
    is their name; "class variables" just sounds like they would belong
    to only the class. But of course subclasses also "belong" to that
    class so there is some logic to it.

    If they were more common I'd vote for adding more syntax (x :))
    but I tend to use both of them seldomly so don't really see the need.

    Maybe this "quirk" should be added (or already have been) to some wiki page
    for newcomers? Or is it obvious to everyone else?

    Regards,

    Robert Feldt



    Robert Feldt Guest

  18. #18

    Default Re: Class variables - a surprising result

    Mark J. Reed wrote:
    > .. . . which are not inherited, which is why it is surprising to many
    > that Ruby's variables are inherited.
    I'm one of them too. Is there a reason that they're implemented the way
    they are? Is it ease of implementation? Based on a different OO
    paradigm? To me it violates the Principle of Least Surprise.

    If I create a class inheriting from FooBar, it seems to me that it's
    dangerous that I can break FooBar and all of its other subclasses by
    doing what appears to be "declaring a class variable" because in reality
    I'm "changing a class variable defined in a superclass".

    Ben


    Ben Giddings Guest

  19. #19

    Default Re: Class variables - a surprising result

    On Fri, Aug 22, 2003 at 04:23:12AM +0900, Michael Campbell wrote:
    > What do you mean by "not inherited"... I'm sure you're correct, but I'm
    > confused:
    You're only confused because you're assuming I'm correct. :) I
    was mistaken; I was thinking of other oddities with static members
    and inheritance.

    -Mark

    Mark J. Reed Guest

  20. #20

    Default Re: Class variables - a surprising result

    On Fri, 22 Aug 2003, Kurt M. Dresner wrote:
    > > I have run into this because I'm working on a loans
    > > system, and each item needs a unique id, which I've allocated as an
    > > error correcting code. This gives me 46000 items. But if I have to
    > > use the same class variable to number my users uniquely as well as
    > > the items they borrow, that uses up space in my limited range.
    >
    > Um, this screams "instance variables" to me...
    Each has an instance var holding its number. Somewhere I must keep
    the next available number, in such a way that the new item gets a
    different one.

    Now I've put it in those terms I might be better having a factory
    class which has an instance var for the number, and calls the
    constructor for the object I want numbered with that fresh
    number....

    ... Item.new(next_free) ...

    Why didn't I think of that before? Keep the number somewhere else
    than the class I want to count.
    >
    > What does your class represent, a user or a loan?
    I have users, loans, and items to be loaned. The loans aren't
    numberd, just the users and items.
    >
    > -Kurt
    >
    >
    Hugh

    Hugh Sasse Staff Elec Eng Guest

Page 1 of 3 123 LastLast

Similar Threads

  1. #25377 [Bgs]: Class variables can be added out of class definition
    By helly@php.net in forum PHP Development
    Replies: 0
    Last Post: November 22nd, 08:24 PM
  2. Replies: 0
    Last Post: November 18th, 08:38 PM
  3. Instance- and class-variables (was mixing in class methods)
    By dblack@superlink.net in forum Ruby
    Replies: 2
    Last Post: October 3rd, 03:52 AM
  4. Instance- and class-variables (was mixing in class methods)
    By dblack@superlink.net in forum Ruby
    Replies: 0
    Last Post: October 2nd, 04:19 PM
  5. Instance- and class-variables (was mixing in class methods)
    By dblack@superlink.net in forum Ruby
    Replies: 0
    Last Post: October 2nd, 12:46 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139