2011-01-07 3 views
17

免責事項:コードは、これは、クラスの中にスコープの定数の議論からですruby koansルビー:クラス定義の明示的なスコープ

から取られました。ここでカップルいくつかのクラスのdefintionです:

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 

2でMyAnimals::Bird.new.legs_in_bird結果をしているこの時点では、私は理由を理解 - 継承階層構造の前に定数の字句スペースを検索します。

次に、このクラスが定義されています

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

チュートリアルでは、今4でMyAnimals::Oyster.new.legs_in_oyster結果を呼び出すことを言うと、私はそれを把握することはできません。オイスターはMyAnimalsのネストされたクラスなので、私はそれがBirdsクラスと同じ方法で動作することを期待していました。明示的なスコープでクラスオイスターを宣言することに関する重要な情報が欠落しています。

誰でもこのことを私に説明できますか?私はGoogleを介して何百ものルビークラスのチュートリアルを見つけましたが、どれもこの状況に対処していません。それがある -

あなたはMyAnimalsクラス定義オイスターINSIDEを定義した場合、あなたはlegs_in_oysterは、あなたが別途オイスターを定義した場合2.

あるという答えを得る...事前に

+3

。はい。四。足!!! zetetic

+0

4本足が良い、2本足が悪い

+3

最初にどの定数に達するかに依存するコードを書く人はいますか? –

答えて

17

私はthis exampleがそれを最もよく説明していると思います。囲み範囲

    1. 任意外側のスコープ(トップレベルに達するまで繰り返す)まで任意外側のスコープ(しかしトップレベル
    2. 含まない を:ルビーは、この順に一定の定義を検索します
    3. 含まモジュール
    4. スーパークラス(ES)
    5. トップレベル
    6. オブジェクト
    7. このエラーを指摘してMark Ameryから
    8. カーネル

    EDIT

    感謝。最上位レベルは、囲みスコープおよび/またはスーパークラスが存在しない場合にのみ到達する。リンクされた例は実際にこれを明らかにします、悲しいことに私はそれを間違って読んでいます。

    この場合の例:あり

    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

    「トップレベル」は何を構成していますか?私が 'FOO = 'topoffile'をしたら;クラステスト; FOO = 'インスペクタークラス'。終わり;クラスTest2 <テスト; def print_foo;プリントFOO;終わり;終わり; Test2.new.print_foo'(私に許してください。長いコードスニペットではコメントがあまりないので、読みやすいように再フォーマットする必要があるかもしれません)私は ''peropclass ''を得ています。これは間違いなくスーパークラスから来ています。外側の範囲で利用可能です。この答えの中の何かが、たとえそれが端の場合だけであっても間違っているようです。 –

    +0

    @MarkAmery良いキャッチ。 – zetetic

    5

    をありがとうLEGS = 2がスコープから外れた後で定義すると、4という応答が返されます。

    これはネストされたクラスがネームスペースとは異なる動作をしていることを示しています。

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

    「Rubyプログラミング言語」によれば、定数は、それらが最初に使用されている場所のレキシカルスコープ内で検索し、継承階層第二にさ。では、Animalを継承するものの字句範囲は何ですか?動物自体、そうですか? MyAnimalsクラスはLEGSを再定義するので、LEGSを使用し、内に MyAnimalsと定義されているものは、まずMyAnimals内のLEGSを探します。

    +0

    ああ、クラスを定義した場所に関係なく、MyAnimals ::それをネストされたクラスにして、そのスコープにアクセスできるようにしました... – jaydel

    関連する問題