Problem assigning an Array object to an Array-subclass object

D

David A. Black

Hi --

# My idea of how to convert an array of strings to a string with a specified
delimiter

That sounds an awful lot like Array#join....
class MyArrayType1 < Array
def [](a)
puts "Entering MyArrayType1#[](a) -- calling parent"
super a
end
def to_s
s = ""
self.each { |x|
s += "; " if s.length>0
s += x.to_s
}
s
end

Yikes -- let Ruby do the work for you:

def to_s
join("; ")
end

:)
end

myA1 = MyArrayType1['x1', 'y1'] # uses the Array#[](a) method with an Array
argument and sets

Actually it's a different [] method that's getting called. It works
like this (using Array instead of MyArrayType1 for convenience):

Array[1,2,3]

is just Ruby shorthand for this:

Array.[](1,2,3)

i.e., call the method [] on the object Array (which is a Class object),
with the arguments (1,2,3).

That's different from, say, this:

a = [1,2,3]
puts a[0] # call [] on a, which is an Array object (i.e., an
# instance of Array)

In other words, the Class object Array responds to [], and so does
every array... but the two [] methods are not the same as each other.
Indeed, there's no connection between these two methods, except that
they happen to have been given the same name. What the class object
Array does or does not respond to is an entirely separate matter from
the matter of what a given instance of the class Array responds to.
Like much else in Ruby, it comes down to the "a class is, itself, an
object" principle.

Here's how it's set up, at least conceptually:

class Array
def Array.[](*args)
# gets called when you do Array[1,2,3]
end

def [](*args)
# gets called when you do
# a = [1,2,3]; puts a[0]
end
end

The first [] is a singleton (i.e., callable through one object only)
method belonging to the Class object Array; singleton methods
belonging to class objects are also referred to as "class methods".
The second [] is an instance method of Array -- meaning, a method to
which every instance of Array will respond.


David
 
R

Richard Lionheart

Hi David,

In an amazing coincidence, I just emailed you (at (e-mail address removed)) because
I wanted to thank you for posting a nice test/unit example and to show you
the minor changes I made to make the example more compelling, or at least
amusing (to me, at least.)

Thank you very much for your excellent explanation to my current question.
That sounds an awful lot like Array#join....
Yikes -- let Ruby do the work for you ...

Yes indeed. A number of people pointed that out to me earlier in this
thread and I have taken their advice to heart. I just posted my original
code with some new comments to ask Ara about the comments. I just read
your analysis quickly but it looks right on target. I'll study it and apply
that to my code and then comments. I've got about a dozen different ways of
doing a few different tasks with arrays that might make an interesting
tutorial for some newbies, i.e. less experienced in Ruby than me.

Regards,
Richard
 
J

Jean-Hugues ROBERT

Hi,

Thanks to reading your code I learned that new syntax to create an array:
x = Array[1,2,3].
So far I used to do:
x = [1,2,3]

But using Array.[]() is cool if I want to create a subclass of Array.

So I tried:
class MyArray < Array
def self.[](*a); super[*a] end
end
x = MyArray[1,2,3] # => NoMethodError: super: no superclass method '[]'

I don't understand what is happening because obviously Array.[]()
exists. In fact it is the only class method defined by Array:
Array.methods( false) # nota: false to avoid inherited methods, not in my
Pickaxe
MyArray.methods( false) # => ["[]"] in both cases.

BTW: In your code you redefine [](a), the instance method, whereas in mine
I redefined self.[](*), the class method. I don't think that [](a) gets
called at all in your example, only your to_s() is called.

???

Yours,

Jean-Hugues

# My idea of how to convert an array of strings to a string with a specified
delimiter
class MyArrayType1 < Array
def [](a)
puts "Entering MyArrayType1#[](a) -- calling parent"
super a
end
def to_s
s = ""
self.each { |x|
s += "; " if s.length>0
s += x.to_s
}
s
end
end

myA1 = MyArrayType1['x1', 'y1'] # uses the Array#[](a) method with an Array
argument and sets
# myA1 to a reference to a new object of
type MyArrayType1
# which is an Array of two strings, 'x1'
and 'y1'
# with an over-ridden 'to_s' method
puts "myA1 = MyArrayType1['x1', 'y1']; puts myA1.to_s ==> " + myA1.to_s #
==> x1; y1
 
D

David Alan Black

Hi --

Jean-Hugues ROBERT said:
Hi,

Thanks to reading your code I learned that new syntax to create an array:
x = Array[1,2,3].
So far I used to do:
x = [1,2,3]

But using Array.[]() is cool if I want to create a subclass of Array.

So I tried:
class MyArray < Array
def self.[](*a); super[*a] end
end
x = MyArray[1,2,3] # => NoMethodError: super: no superclass method '[]'

I get a different error message (wrong # of arguments) -- but in any
case, keep in mind that when you call "super", you're already calling
Array.[] -- so if you add [*a] to that call, you're doing:

Array[1,2,3][1,2,3]

If you just use "super" by itself it will automatically propagate all
the arguments up to the super method.


David
 
K

Kristof Bastiaensen

Hi,

So I tried:
class MyArray < Array
def self.[](*a); super[*a] end
end
x = MyArray[1,2,3] # => NoMethodError: super: no superclass method '[]'

I don't understand what is happening because obviously Array.[]()
exists. In fact it is the only class method defined by Array:
Array.methods( false) # nota: false to avoid inherited methods, not in my
Pickaxe
MyArray.methods( false) # => ["[]"] in both cases.

Perhaps that's because super works only as a method (not as
an object).
Try this:

class MyArray < Array
def self.[](*a); super(*a) end
end

Kristof
 
D

David A. Black

Hi --

Hi,

So I tried:
class MyArray < Array
def self.[](*a); super[*a] end
end
x = MyArray[1,2,3] # => NoMethodError: super: no superclass method '[]'

I don't understand what is happening because obviously Array.[]()
exists. In fact it is the only class method defined by Array:
Array.methods( false) # nota: false to avoid inherited methods, not in my
Pickaxe
MyArray.methods( false) # => ["[]"] in both cases.

Perhaps that's because super works only as a method (not as
an object).
Try this:

class MyArray < Array
def self.[](*a); super(*a) end
end

Or just:

def self.[](*a); super; end


David
 
J

Jean-Hugues ROBERT

Hi,

So I tried:
class MyArray < Array
def self.[](*a); super[*a] end
end
x = MyArray[1,2,3] # => NoMethodError: super: no superclass method '[]'
I don't understand what is happening because obviously Array.[]()
exists. In fact it is the only class method defined by Array:
Array.methods( false) # nota: false to avoid inherited methods, not in my
Pickaxe
MyArray.methods( false) # => ["[]"] in both cases.

Perhaps that's because super works only as a method (not as an object).
Try this:
class MyArray < Array
def self.[](*a); super(*a) end
end
Kristof

Thanks. I obviously was "perhaps" wrong ;-)
Now I get a better understand about why callable's [] is
equivalent to .call() ! They really look similar.

I knew there was a bug in my code because I had applied
Sherlock Holmes' method:
"Eliminate all other factors, and the one which remains
must be the truth." -- The Sign of the Four
I just could not see it.
Thanks again.

Yours,

Jean-Hugues
 
J

Jean-Hugues ROBERT

So I tried:
class MyArray < Array
def self.[](*a); super[*a] end
end

class MyArray < Array
def self.[](*a); super(*a) end
end

Or just:

def self.[](*a); super; end

David

Yes ! You make my day:
super # calls same method in super class, with the current method's
parameters
super() # calls same method in super class, without any parameters
Subtle and convenient. Hum... now I may have to refactor some of my code :)

Yours,

Jean-Hugues
 

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,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top