2017-03-12 3 views
0

Code-Schnipsel unten gibt ein Objekt zurück.Ruby-Objekt vs. Hash

class Person 
    def initialize(name, gender) 
    @name = name 
    @gender = gender 
    end 
end 
x = Person.new("Dan", "M") 
=> #<Person:0x007f6f96600560 @name="Dan", @gender="M"> 
  • Was ist der Unterschied zwischen einem Objekt <...> und einem Hash { ... }? Warum würde eine Ruby-Klasse nicht einfach Hashes zurückgeben?
  • Was ist die 0x007f6f96600560 im Objekt? Ich bin mir ziemlich sicher, dass es nicht object_id ist.
+3

'0x00 ...' ist '(object_id << 1) .to_s (16)' ('object_id', nach links verschoben um eine von 16 Ziffernbasen.) Über das, was das Objekt in OOP ist, gibt es Tonnen geschriebener Bücher. Sie sollten nicht erwarten, eine Antwort auf SO für diese Art von Fragen zu erhalten, denn diese Leute studieren Jahre und lesen viele Bücher. – mudasobwa

+1

Das OP scheint implizit zu suggerieren, dass alle Klassen von 'Hash' subclassiert werden sollten und Instanzvariablennamen und -werte als Schlüssel/Wert-Paare in ihnen gespeichert werden sollten. In der Tat funktioniert JavaScript in etwa so. – sawa

+3

Kurze Antwort: Weil Ruby keine prototypbasierte Sprache ist (https://en.wikipedia.org/wiki/Prototype-based_programming). –

Antwort

0

Natürlich können Sie manchmal Objekte und Hashes für die gleiche Sache verwenden. Speichern von Schlüsselwertpaar ob Objekte wie folgt aus:

[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"} 

Aber diese Objekte bekommt wirklich nicht die ganze Kraft eines Objekts oriente Programmiersprache aus den Definitionen eines class/object und hash:

Ruby eine perfekte objektorientierte Programmiersprache. Die Merkmale der objektorientierten Programmiersprache sind:

Data Encapsulation: 

Data Abstraction: 

Polymorphism: 

Inheritance: 

Diese Eigenschaften haben in Object Oriented Rubin diskutiert.

Ein objektorientiertes Programm umfasst Klassen und Objekte. Eine Klasse ist der Entwurf, aus dem einzelne Objekte erstellt werden. In objektorientierten Begriffen sagen wir, dass Ihr Fahrrad eine Instanz der Klasse von Objekten ist, die als Fahrräder bekannt sind.

Nehmen Sie das Beispiel eines Fahrzeugs. Es besteht aus Rädern, Pferdestärken und Kraftstoff- oder Gastankkapazität. Diese Merkmale bilden die Datenelemente der Klasse Fahrzeug. Mit Hilfe dieser Merkmale können Sie ein Fahrzeug von anderen unterscheiden.

Ein Fahrzeug kann auch bestimmte Funktionen haben, wie z. B. Anhalten, Fahren, und Geschwindigkeitsüberschreitung. Auch diese Funktionen bilden die Datenelemente der Klasse Fahrzeug. Sie können daher eine Klasse als eine Kombination aus Merkmalen und Funktionen definieren.

und eine hash:

Ein Hash ist eine Sammlung von Schlüsselwert-Paaren wie folgt aus: "employee" => "Gehalt". Es ähnelt einem Array, nur dass die Indizierung über beliebige Schlüssel eines beliebigen Objekttyps erfolgt, keinen Integer-Index.

Also zum Speichern von Daten empfehle ich Ihnen einen Hash.

Auf der anderen Seite, wie in einem Kommentar die Zahl zeigte, dass in der Objektdarstellung Appers ist die Objekt-ID, aber mit wenigen Operationen hinzugefügt:

1) bitweise Verschiebung nach links:

5 << 1 # gives 10 

2) bestanden

(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" 

schließlich in ruby ​​hexadeimal Sie die Hash-Darstellung eines Objekts wie folgt zu erreichen:

x.instance_variables.each {|var| hash[var.to_s.delete("@")] = x.instance_variable_get(var) } 
1

Objekt → Hash

Aus dem ausgezeichneten Buch "Ruby under the microscope" von Pat Shaughnessy:

Jedes Ruby-Objekt ist die Kombination aus einem Klassenzeiger und ein Array von Instanzvariablen.

Here ist eine etwas längere Beschreibung:

Ein benutzerdefiniertes Ruby-Objekt durch eine Struktur repräsentiert wird genannt ein RObject, und wird durch einen Zeiger genannt Wert bezeichnet.

In RObject gibt es eine andere Struktur namens RBasic, die alle Ruby-Werte haben wird.

Abgesehen von der RBasic Struktur RObject enthält auch numiv, eine Zählung davon, wie viele Instanzvariablen die Aufgabe hat, ivptr, einen Zeiger auf einen Array von Werten der Instanzvariablen und iv_index_tbl, der ist ein Zeiger zu einer Hash-Tabelle, die in der dem Objekt zugeordneten RClass-Struktur gespeichert ist, die den Namen/die Identität jeder Instanzvariable ihrer Position im Array ivtpr zuordnet.

Von jedem Ruby-Objekt, dann ist es möglich, extract a hash of instance variables:

class Object 
    def instance_variables_hash 
    Hash[instance_variables.map { |name| [name, instance_variable_get(name)] } ] 
    end 
end 

Mit Ihrem Beispiel:

x.instance_variables_hash 
=> {:@name=>"Dan", :@gender=>"M"} 

Hash → Objekt?

Aber Sie könnten unmöglich x zurück von diesem Hash erstellen, weil Sie eine entscheidende Information fehlt: Welche Klasse ist x eine Instanz von?

So zum Beispiel, würden Sie die Methoden nicht wissen, dass Sie x schicken:

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"> 

object_id

Um die object_id aus dem inspizieren Zeichenfolge zu erhalten:

"0x007f6f96600560".sub('0x','').to_i(16)/2 
#=> 70058620486320 

Und zurück:

"0x" + (70058620486320 * 2).to_s(16).rjust(14,'0') 
#=> "0x007f6f96600560"