2011-01-07 7 views
17

Haftungsausschluss: Code aus den aufgenommenen ruby koansRubin: expliziter Scoping auf einer Klassendefinition

Diese aus einer Diskussion von Konstanten ist innerhalb von Klassen Scoping. Hier ist die Defintion von ein paar wenigen Klassen:

class Animal 
    LEGS = 4 
    def legs_in_animal 
    LEGS 
    end 
end 

class MyAnimals 
    LEGS = 2 

    class Bird < Animal 
    def legs_in_bird 
     LEGS 
    end 
    end 
end 

An dieser Stelle tut MyAnimals::Bird.new.legs_in_bird Ergebnisse in 2 und ich verstehe, warum - lexikalischen Raum für die Konstante vor der Vererbungshierarchie suchen.

Dann wird diese Klasse definiert:

class MyAnimals::Oyster < Animal 
    def legs_in_oyster 
    LEGS 
    end 
end 

Das Tutorial sagt nun, dass MyAnimals::Oyster.new.legs_in_oyster Ergebnisse in 4 Aufruf und ich kann es nicht herausgefunden. Es scheint mir, dass Oyster eine geschachtelte Klasse in MyAnimals ist und ich erwartete, dass sie sich genauso verhält wie die Birds Klasse. Ich vermisse einige wichtige Informationen darüber, was die Klasse Oyster mit expliziten Scoping-Mitteln deklariert.

kann mir jemand das erklären? Ich habe Hunderte von Ruby-Kurs-Tutorials über Google gefunden, aber keine von ihnen adressiert diese Situation.

Vielen Dank im Voraus ...

+3

Es. Sind. VIER. Beine !!! zetetic

+0

Vier Beine gut, zwei Beine schlecht

+3

schreibt jemand Code, der davon abhängen würde, welche Konstante zuerst erreicht würde? –

Antwort

17

Ich denke this example erklärt es am besten.Rubin sucht die konstante Definition in dieser Reihenfolge:

  1. Der umschließenden Umfang
  2. Alle äußeren Bereiche (bis oberster Ebene wiederholen erreicht ist) Irgendwelche äußeren Bereiche (bis zu aber ohne die Top-Level-
  3. Enthaltene Module
  4. Superklasse (n)
  5. Top Level
  6. Objekt
  7. Kernel

EDIT

Dank für den Hinweis Mark Amery diesen Fehler aus. Die oberste Ebene wird nur erreicht, wenn keine umschließenden Bereiche und/oder Oberklassen vorhanden sind. Das verlinkte Beispiel macht dies deutlich, leider habe ich es falsch gelesen.

Ein Beispiel für diesen Fall:

FOO = 'I pity the foo!' 

module One 
    FOO = 'one' 

    class Two 
    FOO = 'two' 

    def self.foo 
     FOO 
    end 
    end 

    class Three < Two 
    def self.foo 
     FOO 
    end 
    end 
end 

class Four 
    class Five < Four 
    def self.foo 
     FOO 
    end 
    end 
end 

describe FOO do 
    it "depends where it is defined" do 
    expect(FOO).to eq 'I pity the foo!' # top-level 
    expect(One::FOO).to eq 'one' # module 
    expect(One::Two.foo).to eq 'two' # class 
    expect(One::Three.foo).to eq 'one' # outer scope (One) comes before superclass 
    expect(Four::Five.foo).to eq 'I pity the foo!' # top-level 
    end 
end 
+0

Was macht die "oberste Ebene"? Wenn ich 'FOO = 'topoffile' mache; Klasse Test; FOO = "Unterklasse"; Ende; Klasse Test2

+0

@MarkAmery guter Fang. – zetetic

5

Wenn Sie die Auster INSIDE die MyAnimals Klassendefinition definieren Sie die Antwort dann erhalten, dass legs_in_oyster ist 2.

Wenn Sie die Oyster separat definieren - das ist , Sie definieren es, nachdem LEGS = 2 den Gültigkeitsbereich verlassen hat, erhalten Sie die Antwort von 4.

Dies deutet darauf hin, dass die geschachtelte Klasse anders verhält als ein Namespace, vielleicht eher wie eine Schließung.

--- EDIT ---

irb(main):076:0> class MyAnimals::RunningRoach < Animal; def using_legs; LEGS; end; end 
=> nil 
irb(main):077:0> MyAnimals::RunningRoach.new.kind_of?(MyAnimals) 
=> false 
irb(main):078:0> MyAnimals::RunningRoach.new.kind_of?(Animal) 
=> true 
irb(main):081:0> class MyAnimals::Mantis < MyAnimals; def killing_legs; LEGS; end; end 
=> nil 
irb(main):082:0> MyAnimals::Mantis.new.kind_of?(Animal) 
=> false 
irb(main):083:0> MyAnimals::Mantis.new.kind_of?(MyAnimals) 
=> true 
irb(main):084:0> MyAnimals::Mantis.new.killing_legs 
=> 2 
irb(main):085:0> MyAnimals::RunningRoach.new.using_legs 
=> 4 

Laut "The Ruby-Programmiersprache", Konstanten sind in dem lexikalischen Gültigkeitsbereich des Orts nachgeschlagen, wo sie zum ersten Mal verwendet werden, und in der Vererbungshierarchie zweiten . Also, was ist der lexikalische Umfang von etwas, das Tier erbt? Tier selbst, oder? Die MyAnimals-Klasse definiert LEGS neu, also wird alles, was LEGS verwendet und innerhalb von MyAnimals definiert ist, zuerst nach LEGS in MyAnimals suchen.

+0

Ah, ich dachte, dass egal, wo du die Klasse definiert hast, die Handlung von MyAnimals: darauf machte es eine geschachtelte Klasse und gab ihm Zugriff auf diesen Bereich ... – jaydel