3

構文について他にも質問があることは承知していますclass << self。それでも、これらの答えは十分に明確ではありませんでした。私は Java/C#、C のバックグラウンドを持っているので、Ruby は私にとってちょっと変わったものです。class << self私はそれがシングルトンクラスを指していると読みました。これはちょっと複雑なので、このコンテキストでオペレーターが何をするのか、両端に何ができるのかを理解したいと思います。<<この構文を理解するのに役立つ簡単なコードを作成しようとしました (私の質問はコードにあります)。

class Self

def Self.selfTest
end

def onSelf
    class << Self   #I know this might be strange. 
        self
    end

end

def onself
    class << self
        self
    end
end

end

s = Self.new
onSelf = s.onSelf
onself = s.onself

#Here, i wanna know what kind of references are returned. 

puts "onSelf responds to onSelf:#{onSelf.respond_to?(:onSelf)}"
puts "onSelf responds to selfTest:#{onSelf.respond_to?(:selfTest)}"
puts "onself responds to onSelf:#{onself.respond_to?(:onSelf)}"
puts "onself responds to selfTest:#{onself.respond_to?(:selfTest)}"

#Output:
#onSelf responds to onSelf:false
#onSelf responds to selfTest:false
#onself responds to onSelf:false
#onself responds to selfTest:true

#So, i conclude that the second one is a reference to a class. What is the first one???????


puts onSelf
puts onself

#Output
#<Class:Self>
#<Class:#<Self:0x007f93640509e8>>

#What does this outputs mean???????

def onSelf.SelfMet
    puts 'This is a method defined on base class'
end


def onself.selfMet
    puts 'This is a method defined on metaclass'
end



puts "Does Self Class respond to SelfMet? : #{Self.respond_to?(:SelfMet)}"
puts "Does Self Class respond to selfMet? : #{Self.respond_to?(:selfMet)}"
puts "Does Self instance respond to SelfMet? : #{s.respond_to?(:SelfMet)}"
puts "Does Self instance respond to selfMet? : #{s.respond_to?(:selfMet)}"

#Output
#Does Self Class respond to SelfMet? : false
#Does Self Class respond to selfMet? : false
#Does Self instance respond to SelfMet? : false
#Does Self instance respond to selfMet? : false

#Why won't they respond to defined methods???? 

ありがとう

更新: どうもありがとうございました。私はたくさん読んでテストしたので、いくつかの考慮事項を残します。今後の参考のためにこれを残しておきますので、Ruby の専門家が私が間違っている場合は修正してくれることを願っています。クラス << Self が Self シングルトン クラスを参照していることに気付きました。したがって、慣用的なクラス << abcd は、abcd シングルトン クラス コンテキストを開始します。また、クラスのシングルトン クラスの階層は、オブジェクトのシングルトン クラスとは異なることに気付きました。クラス シングルトン クラスの階層は、階層上のすべてのシングルトン クラスに従います。この場合:

singleton Self->singleton Object->Singleton basicobject ->class->module->object->kernel->basicObject

オブジェクト シングルトン クラスは、別の種類の階層にあります。

オブジェクト singleton->Self->Object->kernel->basicObject

これは、この出力を説明しています。

4

2 に答える 2

2

おそらくこれが役立つでしょう。次のステートメントを追加すると、示された結果が得られます。

puts onSelf                         #=> #<Class:Self> 
puts Self.singleton_class           #=> #<Class:Self>
puts onSelf == Self.singleton_class #=> true

puts onself                         #=> #<Class:#<Self:0x007fe6330aab10>>
puts s.singleton_class              #=> #<Class:#<Self:0x007fe6330aab10>>
puts onself == s.singleton_class    #=> true

レシーバーがメタクラスであるメソッドを定義しても意味がありませんが、それはあなたが行ったことです。

puts onSelf.SelfMet
  #=> This is a method defined on Self's metaclass

puts onself.selfMet
  #=> This is a method defined on s's metaclass

明らかに、onSelf( Self.singleton_class) は応答しますSelfMet(ただし には応答しませんselfmet)、onself( s.singleton_class) は応答しますselfmet(ただし には応答しませんSelfmet)。

がにSelf応答するにSelfMetは、後者をdef Self.SelfMet...or def self.SelfMet..(または他のいくつかの方法のいずれか) で定義する必要がありますが、そうではありません。

同様に、 がsに応答するにselfMetは、後者を通常のインスタンス メソッドとして定義するdef selfMet...(この場合、 の他のすべてのインスタンスSelfもそれに応答する) か、sのシングルトン クラスで定義する必要def s.selfMet...があります (この場合、 Self の他のインスタンスはそれに応じない)。

Selfつまり、インスタンスがシングルトン メソッドに応答するのと同様に、クラスはそのシングルトン メソッドにs応答します。と のシングルトン クラスはSelfsそれぞれのシングルトン メソッドに応答しません。

以下は、ここで何が起こっているかを理解するのに役立つかもしれません。それぞれの後に続く文は、文がRubyによって実行されたときにp self続くものを#=>表示します。、#=>などのさまざまなステートメントを使用して、 の値を目的の値に変更する方法に注目してください。 メタプログラミング時の親友です。class Dogclass << selfselfp self

p self            #=> main

class Dog
  p self          #=> Dog

  def self.woof1
    p self
  end

  def Dog.woof2
    p self
  end

  p self          #=> Dog

  class << self
    p self                #=> #<Class:Dog>
    p Dog.singleton_class #=> #<Class:Dog>  
    def woof3
      p self
    end
  end

  p self          #=> Dog

  def woof4
    p self
  end
end

p self            #=> main

def Dog.woof5
  p self
end

Dog.instance_eval do
  p self          #=> Dog
  def woof6
    p self
  end
end  

dog = Dog.new     #=> #<Dog:0x007fe17b08cf00> 

def dog.woof7
  p self
end

dog.instance_eval do
  p self          #=> #<Dog:0x007fe17b08cf00>
  def woof8
    p self
  end
end  

p self            #=> main

Dog.woof1 #=> Dog
Dog.woof2 #=> Dog
Dog.woof3 #=> Dog
Dog.woof5 #=> Dog
Dog.woof6 #=> Dog

dog.woof4 #=> #<Dog:0x007fe17b08cf00>
dog.woof7 #=> #<Dog:0x007fe17b08cf00>
dog.woof8 #=> #<Dog:0x007fe17b08cf00>

puppy = Dog.new #=> #<Dog:0x007fe17ba93a08>
puppy.woof4     #=> #<Dog:0x007fe17ba93a08>
puppy.woof7 #=> undefined method `woof7' for #<Dog:0x007fe5fb3e1d48>
puppy.woof8 #=> undefined method `woof8' for #<Dog:0x007fe5fb3e1d48>

すべてを整理するにはしばらく時間がかかります。それでも、私たちのほとんどは時々復習が必要です。これは、このテーマに関する優れた記事です。また、そこにあるコメントの参考文献、特に Dave Thomas のプレゼンテーションも参照してください。

最後に、Ruby の命名規則を見てください。

于 2014-02-08T01:44:52.220 に答える