Reputation:
Code snippet below returns an object.
class Person
def initialize(name, gender)
@name = name
@gender = gender
end
end
x = Person.new("Dan", "M")
=> #<Person:0x007f6f96600560 @name="Dan", @gender="M">
< ... >
and a hash { ... }
? Why wouldn't a Ruby class just return hashes? 0x007f6f96600560
in the object? I am pretty sure it's not object_id
.Upvotes: 5
Views: 9892
Reputation: 54303
From the excellent book "Ruby under the microscope" by Pat Shaughnessy :
Every Ruby object is the combination of a class pointer and an array of instance variables.
Here's a somewhat longer description :
A user-defined Ruby object is represented by a structure called an RObject, and is referred to by a pointer called VALUE.
Inside RObject, there is another structure called RBasic, which all Ruby values will have.
Aside from the RBasic structure, RObject also contains numiv, a count of how many instance variables the object has, ivptr, a pointer to an array of values of the instance variables, and iv_index_tbl, which is a pointer to a hash table stored in the object’s associated RClass structure that maps the name/identity of each instance variable to its position in the ivtpr array.
From any Ruby object, it's possible to extract a hash of instance variables :
class Object
def instance_variables_hash
Hash[instance_variables.map { |name| [name, instance_variable_get(name)] } ]
end
end
With your example :
x.instance_variables_hash
=> {:@name=>"Dan", :@gender=>"M"}
But you couldn't possibly create x
back from this hash, because you're missing a crucial piece of information : what class is x
an instance of?
So for example, you wouldn't know the methods that you can send to x
:
class Dog
def initialize(name, gender)
@name = name
@gender = gender
end
def bark
puts "WOOF"
end
end
person = Person.new("Dan", "M")
dog = Dog.new("Dan", "M")
p person.instance_variables_hash
# {:@name=>"Dan", :@gender=>"M"}
p dog.instance_variables_hash == person.instance_variables_hash
# true
person.bark
# undefined method `bark' for #<Person:0x007fb3b20ed658 @name="Dan", @gender="M">
To get the object_id out of the inspect string :
"0x007f6f96600560".sub('0x','').to_i(16)/2
#=> 70058620486320
And back :
"0x" + (70058620486320 * 2).to_s(16).rjust(14,'0')
#=> "0x007f6f96600560"
Upvotes: 8
Reputation: 11542
Of course, some times you can use objects and hashes for the same thing. Storing key value pair ob objects like this:
[3] pry(main)> class Person
def initialize(name, gender)
@name = name
@gender = gender
end
end
[3] pry(main)* => :initialize
[4] pry(main)> x = Person.new("Dan", "M")
=> #<Person:0x00000003708098 @gender="M", @name="Dan">
[13] pry(main)> y = Person.new("Peter", "M")
=> #<Person:0x0000000391fca0 @gender="M", @name="Peter">
[22] pry(main)> z = {name: "Maria", gender: "F"}
=> {:name=>"Maria", :gender=>"F"}
But this objects really doesn't get all the power of an object oriente programming language from the definitions of an class/object and hash:
Ruby is a perfect Object Oriented Programming Language. The features of the object-oriented programming language include:
Data Encapsulation: Data Abstraction: Polymorphism: Inheritance:
These features have been discussed in Object Oriented Ruby.
An object-oriented program involves classes and objects. A class is the blueprint from which individual objects are created. In object-oriented terms, we say that your bicycle is an instance of the class of objects known as bicycles.
Take the example of any vehicle. It comprises wheels, horsepower, and fuel or gas tank capacity. These characteristics form the data members of the class Vehicle. You can differentiate one vehicle from the other with the help of these characteristics.
A vehicle can also have certain functions, such as halting, driving, and speeding. Even these functions form the data members of the class Vehicle. You can, therefore, define a class as a combination of characteristics and functions.
and a hash:
A Hash is a collection of key-value pairs like this: "employee" => "salary". It is similar to an Array, except that indexing is done via arbitrary keys of any object type, not an integer index.
So for store data I recommend you a Hash.
On the other hand, as showed in a comment the number that appers in the object representation is the object id, but with few operations added:
1) bitwise left shift:
5 << 1 # gives 10
2) passed to hexadeimal
(10).to_s(16)
"a"
pry(main)> x = Person.new("Dan", "M")
=> #<Person:0x00000003708098 @gender="M", @name="Dan">
[5] pry(main)> x.object_id
=> 28852300
[8] pry(main)> (x.object_id << 1 ).to_s(16)
=> "3708098"
finally in ruby you can get the hash representation of an object like this:
x.instance_variables.each {|var| hash[var.to_s.delete("@")] = x.instance_variable_get(var) }
Upvotes: 3