subclassing fundamental classes

Discussion in 'Ruby' started by Dan Zwell, May 8, 2007.

  1. Dan Zwell

    Dan Zwell Guest

    xyz wrote:
    > Let's say I have a user-defined class as follows:
    >
    > class C1
    > #-------------------------
    > def initialize(i, j)
    > @iv1 = Array.new(i, j)
    > end
    > #-------------------------
    > def append(i)
    > @iv1 << i
    > return(self)
    > end
    > #-------------------------
    > def append2X(i)
    > @iv1 << 2 * i
    > return(self)
    > end
    > #-------------------------
    > end
    >
    > Now I subclass C1 to make C2:
    >
    > class C2 < C1
    > #-------------------------
    > def initialize(inA)
    > @iv1 = inA
    > end
    > #-------------------------
    > def append(i)
    > @iv1 << i << i
    > return(self)
    > end
    > #-------------------------
    > def doubleLast()
    > @iv1[-1] *= 2
    > return(self)
    > end
    > #-------------------------
    > end
    >
    > The internal state of the superclass (C1) is visible to methods in the subclass
    > (C2) and has a known name that can be used in the subclass (@iv1). Now let's
    > look at a similar situation but where the superclass is one of the "fundamental"
    > classes pre-packaged with Ruby (i.e. Array, Hash, String, etc.). A "fundamental"
    > class is one that is not constructed from some other Ruby class using Ruby
    > source but is instead constructed from the same underlying machinery as the
    > interpreter itself (in the current implementation this means C source). In the
    > following "???" denotes a name for an instance variable in the superclass.
    >
    > class C3 < Array
    > def initialize(inArray)
    > ??? = inArray
    > end
    > def append(i)
    > ??? << i << i
    > return(self)
    > end
    > def join(i)
    > out = ""
    > sep = "#" * i
    > ???.each { |e| out << sep + e.to_s + sep }
    > return(out)
    > end
    > end
    >
    > What do I use in place of the ???'s above? That is, what name do I use in the
    > subclass (C3) for the instance state of a fundamental superclass (Array)?
    >
    > When a superclass is fundamental, can I access instance state in said superclass
    > without having to resort to the underlying C interface?
    >
    > In my specific case, I am using instances of Array to hold data in a particular
    > format (the array elements are Hash's whose keys are String's of a particular
    > format and whose values are Hash's of a particular format). I want to subclass
    > Array, add a couple of methods, override a couple of methods, and also use the
    > non-overridden methods of Array.
    >
    > It looks like I could make this work by simply adding my new methods directly to
    > Array and using alternate (if less descriptive) names for the Array methods I
    > was planning on overriding (this would allow me to access the internal state of
    > Array using self). However this approach will make the code slightly less
    > readable since some Array variables will be generic Array's and some will be my
    > special version. And to make things worse, I actually have two special versions
    > of Array and was planning on constructing two separate subclasses.
    >
    > Thanx.
    >
    > Jake
    >
    >


    I think it's just "self", but you'll have one problem because you can't
    assign a value to self. I would try:

    def initialize(inArray)
    inArray.each {|elem| self << elem}
    end

    Dan
    Dan Zwell, May 8, 2007
    #1
    1. Advertising

  2. Dan Zwell

    xyz Guest

    Let's say I have a user-defined class as follows:

    class C1
    #-------------------------
    def initialize(i, j)
    @iv1 = Array.new(i, j)
    end
    #-------------------------
    def append(i)
    @iv1 << i
    return(self)
    end
    #-------------------------
    def append2X(i)
    @iv1 << 2 * i
    return(self)
    end
    #-------------------------
    end

    Now I subclass C1 to make C2:

    class C2 < C1
    #-------------------------
    def initialize(inA)
    @iv1 = inA
    end
    #-------------------------
    def append(i)
    @iv1 << i << i
    return(self)
    end
    #-------------------------
    def doubleLast()
    @iv1[-1] *= 2
    return(self)
    end
    #-------------------------
    end

    The internal state of the superclass (C1) is visible to methods in the subclass
    (C2) and has a known name that can be used in the subclass (@iv1). Now let's
    look at a similar situation but where the superclass is one of the "fundamental"
    classes pre-packaged with Ruby (i.e. Array, Hash, String, etc.). A "fundamental"
    class is one that is not constructed from some other Ruby class using Ruby
    source but is instead constructed from the same underlying machinery as the
    interpreter itself (in the current implementation this means C source). In the
    following "???" denotes a name for an instance variable in the superclass.

    class C3 < Array
    def initialize(inArray)
    ??? = inArray
    end
    def append(i)
    ??? << i << i
    return(self)
    end
    def join(i)
    out = ""
    sep = "#" * i
    ???.each { |e| out << sep + e.to_s + sep }
    return(out)
    end
    end

    What do I use in place of the ???'s above? That is, what name do I use in the
    subclass (C3) for the instance state of a fundamental superclass (Array)?

    When a superclass is fundamental, can I access instance state in said superclass
    without having to resort to the underlying C interface?

    In my specific case, I am using instances of Array to hold data in a particular
    format (the array elements are Hash's whose keys are String's of a particular
    format and whose values are Hash's of a particular format). I want to subclass
    Array, add a couple of methods, override a couple of methods, and also use the
    non-overridden methods of Array.

    It looks like I could make this work by simply adding my new methods directly to
    Array and using alternate (if less descriptive) names for the Array methods I
    was planning on overriding (this would allow me to access the internal state of
    Array using self). However this approach will make the code slightly less
    readable since some Array variables will be generic Array's and some will be my
    special version. And to make things worse, I actually have two special versions
    of Array and was planning on constructing two separate subclasses.

    Thanx.

    Jake
    xyz, May 8, 2007
    #2
    1. Advertising

  3. On Tue, May 08, 2007 at 03:20:12PM +0900, xyz wrote:
    > class C3 < Array
    > def initialize(inArray)
    > ??? = inArray
    > end
    > def append(i)
    > ??? << i << i
    > return(self)
    > end
    > def join(i)
    > out = ""
    > sep = "#" * i
    > ???.each { |e| out << sep + e.to_s + sep }
    > return(out)
    > end
    > end
    >
    > What do I use in place of the ???'s above? That is, what name do I use in the
    > subclass (C3) for the instance state of a fundamental superclass (Array)?


    self. An Array doesn't store its array in an instance variable; the object
    *is* the array.

    You can add instance variables in your subclass though.

    You may find Array#replace useful, if you want to replace your array
    contents with another array. (So 'self' still points to the same object of
    course, but the array contents are different). This is almost the same as
    having the array in @iv and then changing @iv to point to another array. The
    difference is that if you had @iv, you could point it to some other object
    which *isn't* an array.

    > In my specific case, I am using instances of Array to hold data in a particular
    > format (the array elements are Hash's whose keys are String's of a particular
    > format and whose values are Hash's of a particular format). I want to subclass
    > Array, add a couple of methods, override a couple of methods, and also use the
    > non-overridden methods of Array.


    Consider delegation instead of subclassing. In the long run it gives you
    more flexibility.

    Subclassing is the evil you learn from Object Oriented Programming courses.
    It's taught so thoroughly that you come to believe that subclassing *is*
    OOP. In fact, once you ditch subclassing, and worrying whether a Square is a
    Rectangle or vice versa, life becomes much more straightforward :)

    Regards,

    Brian.
    Brian Candler, May 8, 2007
    #3
  4. On 08.05.2007 09:17, xyz wrote:
    > In my specific case, I am using instances of Array to hold data in a particular
    > format (the array elements are Hash's whose keys are String's of a particular
    > format and whose values are Hash's of a particular format). I want to subclass
    > Array, add a couple of methods, override a couple of methods, and also use the
    > non-overridden methods of Array.


    Please note that more often than not it is not a good idea to do this
    (creating sub classes of core classes). Reason: you typically want some
    specific operations on the content but if your class *is an* Array you
    get all the Array manipulation methods unless you undefine or override
    them. It's typically simpler and cleaner to just make your class *have
    an* Array and only provide the interface to the public that you want to
    allow.

    Kind regards

    robert
    Robert Klemme, May 8, 2007
    #4
  5. Dan Zwell

    xyz Guest

    Array.replace works (at least for my reasonably accurate test code).

    i always wondered why Array, Hash, etc. had replace (which seemed superfluous
    given that i can just do an assign). now i know at least one good reason why -
    they effectively give one a channel to write the instance data of fundamental
    classes.

    and technically (speaking C here since that's what's currently under the hood),
    self isn't the physical array, it's a pointer to an object struct containing an
    RBasic struct, a pointer to an instance variable array (one of whose pointers
    points to an RArray struct which contains the address of the physical array
    storage and the length), and a pointer to the class struct, etc.

    thanx again for the pointer :) to replace.

    jake

    "Brian Candler" <> wrote in message
    news:...
    > On Tue, May 08, 2007 at 03:20:12PM +0900, xyz wrote:
    >> class C3 < Array
    >> def initialize(inArray)
    >> ??? = inArray
    >> end
    >> def append(i)
    >> ??? << i << i
    >> return(self)
    >> end
    >> def join(i)
    >> out = ""
    >> sep = "#" * i
    >> ???.each { |e| out << sep + e.to_s + sep }
    >> return(out)
    >> end
    >> end
    >>
    >> What do I use in place of the ???'s above? That is, what name do I use in the
    >> subclass (C3) for the instance state of a fundamental superclass (Array)?

    >
    > self. An Array doesn't store its array in an instance variable; the object
    > *is* the array.
    >
    > You can add instance variables in your subclass though.
    >
    > You may find Array#replace useful, if you want to replace your array
    > contents with another array. (So 'self' still points to the same object of
    > course, but the array contents are different). This is almost the same as
    > having the array in @iv and then changing @iv to point to another array. The
    > difference is that if you had @iv, you could point it to some other object
    > which *isn't* an array.
    >
    >> In my specific case, I am using instances of Array to hold data in a
    >> particular
    >> format (the array elements are Hash's whose keys are String's of a particular
    >> format and whose values are Hash's of a particular format). I want to
    >> subclass
    >> Array, add a couple of methods, override a couple of methods, and also use
    >> the
    >> non-overridden methods of Array.

    >
    > Consider delegation instead of subclassing. In the long run it gives you
    > more flexibility.
    >
    > Subclassing is the evil you learn from Object Oriented Programming courses.
    > It's taught so thoroughly that you come to believe that subclassing *is*
    > OOP. In fact, once you ditch subclassing, and worrying whether a Square is a
    > Rectangle or vice versa, life becomes much more straightforward :)
    >
    > Regards,
    >
    > Brian.
    >
    xyz, May 9, 2007
    #5
    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. Praveen
    Replies:
    3
    Views:
    563
    Praveen
    Apr 24, 2005
  2. Gary

    FUNDAMENTAL QUESTION 1:

    Gary, Nov 29, 2003, in forum: Java
    Replies:
    3
    Views:
    478
    pete kirkham
    Nov 29, 2003
  3. Gary

    FUNDAMENTAL QUESTION 2:

    Gary, Nov 29, 2003, in forum: Java
    Replies:
    3
    Views:
    416
    Bjorn Abelli
    Nov 29, 2003
  4. Casper Bang
    Replies:
    51
    Views:
    1,206
  5. Alf P. Steinbach
    Replies:
    30
    Views:
    863
    Dave Thompson
    Feb 14, 2005
Loading...

Share This Page