11

プログラミングと Ruby は初めてなので、シンボルに関するこの質問が一致することを願っています。Ruby の記号 ( 、:bookなど:price) は、特にハッシュ キーとして有用であり、文字列が実行できることの軽量で特定のサブセットを全体的に実行するのに役立つことを理解しています。

ただし、ある点で記号について混乱しています。具体的には、attr_accessorメソッドの型で使用すると、変数のように動作しているように見えます。例: attr_reader :book, :price.

それらがその使用法で変数であることが真である場合、変数の型が変数型の場合、変数型 ($global、@instance、local、@@class、場合によっては CONSTANT 変数型など) の中に通常リストされないため、これは少し不可解です。が記述されています。

そして、このように使用されたときにシンボルが変数である場合、それらにはどのようなスコープが期待されるべきでしょうか? それとも、このコンテキストでも何らかの形で軽量の文字列ですか? (または、より広い意味で、シンボル、文字列、および変数はすべて基本的なアヒルのような性質を共有しているのでしょうか?) 洞察とアドバイスをよろしくお願いします。

4

8 に答える 8

7

記号は変数ではなく、数字や引用符で囲まれた文字列などのリテラル値の一種です。重要なことに、シンボルは、Rubyランタイムで変数やその他の名前付きの値を表すために使用されます。したがって、Rubyインタープリターがfoo変数またはメソッド名として使用されている名前を確認すると、実行時値のハッシュで検索されるのは:foo、文字列ではなくシンボル"foo"です。実際、これはプログラミング言語の用語で「記号」という用語が最初に使用されたものです。変数、関数、定数、メソッドなどは、コンパイラまたはインタプリタの「シンボルテーブル」に格納されていると言われます。

Rubyで何かの名前を渡すときは、ほとんどの場合、シンボルを使用します。オブジェクトクラスに任意のメソッドを実装するためのキャッチオールとして使用する場合method_missing、シンボルは、実際に呼び出されたメソッドの名前を示す引数として受け取るものです。.methodsまたはを使用してオブジェクトを検査すると.instance_variables、返されるのはシンボルの配列です。等々。

于 2012-12-13T00:22:01.090 に答える
6

それらは値を保持しないため変数ではなく、不変です。物事は価値そのものです。数字に似ています。の値を設定することはできません11 = 2動作しません。

于 2012-12-13T00:21:45.227 に答える
3

アクセサー メソッドで使用されるシンボルは変数ではありません。それらは変数の名前を表しているだけです。変数はいくつかの参照を保持するため、アクセサ メソッドの定義に変数自体を使用することはできません。たとえば、変数の@foo値が であるコンテキストで変数のアクセサ メソッドを定義したいとします"bar"。Ruby の構文が次のようになったらどうなるでしょうか。

attr_accessor @foo

これは、次のように書くことと同じです。

attr_accessor "bar"

関心のある名前にアクセスできない場合@foo。したがって、そのような構造は、メタ レベルで変数名を参照するように設計する必要があります。このため、シンボルが使用されます。それら自体は変数ではありません。それらは変数の名前を表します。

そして、アクセサー メソッドに関連する変数はインスタンス変数です。

于 2012-12-13T01:14:34.707 に答える
2

attr_accessorこれらは、クラス Class に属するすべてのメソッドです。引数としてシンボルが必要です。attr_必要に応じて、使用されている文字列の独自のバージョンを作成できます。それは単なるルビーのイディオムです。これは、宿題のために作成しattr_acessorた以前のすべての値を保存する例です。attr_accessor

class Class
  def attr_accessor_with_history(attr_name)
    attr_name = attr_name.to_s   # make sure it's a string
    attr_reader attr_name        # create the attribute's getter
    attr_reader attr_name+"_history" # create bar_history getter
    class_eval %Q"
      def #{attr_name}=(value)
        if !defined? @#{attr_name}_history 
          @#{attr_name}_history = [nil]
        end
        @#{attr_name} = value
        @#{attr_name}_history << value
      end
    "
  end
end
于 2012-12-13T00:25:52.943 に答える
1

Rubyのattr_accessor、、、attr_readerおよびattr_writerは、繰り返しコードを少し書くことを避けるための簡単な方法です。次の質問は、これらがどのように機能するかを拡張したものです。なぜRubyのattr_accessor、attr_reader、attr_writerを使用するのですか?

変数attr_reader :bookとして考えるのではなく、シンボルを使用して指定された属性の名前として考えてください。

于 2012-12-13T00:21:15.047 に答える
1

「それらが変数である場合」と「スコープ」の質問に対処するには、偶像破壊的に聞こえるとしても、アクセサーシンボルはインスタンス変数とは何の関係もないと答える方が簡単だったでしょう。それらはインスタンス変数を指していません。アクセサーは、getter メソッドと setterメソッドのみを定義します。Object#instance_variables の下で、Pickaxe(*) は次のように述べています。アクセサを定義するだけでは、対応するインスタンス変数が作成されないことに注意してください。

Ruby では、値を代入するまで変数は存在しません。次のコードはこれを示しています。

class MyClass
    attr_accessor :name
    attr_reader   :book
end

obj = MyClass.new # line 6
print '1) obj.instance_variables : '; p obj.instance_variables
print '2) obj.name : '; p obj.name

obj.name = 'xyz'
print '3) obj.instance_variables : '; p obj.instance_variables
print '4) obj.name : '; p obj.name
print '5) obj.book : '; p obj.book

class MyClass
    def initialize(p_book)
        @book = p_book
    end
end

obj = MyClass.new('The Pickaxe') # line 21
print '6) [new] obj.book : '; p obj.book

class MyClass
    method_name = 'title'
    attr_accessor method_name # line 26
end

obj.title = 'Programming Ruby'
print '7) obj.instance_variables : '; p obj.instance_variables
print '8) obj.title : '; p obj.title

出力:

$ ruby -w t.rb 
1) obj.instance_variables : []
2) obj.name : nil
3) obj.instance_variables : ["@name"]
4) obj.name : "xyz"
5) obj.book : nil
6) [new] obj.book : "The Pickaxe"
7) obj.instance_variables : ["@title", "@book"]
8) obj.title : "Programming Ruby"

1) 空の配列: アクセサーはインスタンス変数を定義していません
2) インスタンス変数 @name を要求すると nil が返されます: 存在しません
3) 値を割り当てるとインスタンス変数が作成されました。は、セッターをパラメーター付きの通常のメソッドとして使用するための構文糖衣であることに
注意してください: 4) ゲッター メソッドは @name の値に応答します 5)インスタンス変数 @book が存在しないため、ゲッター メソッドは nil に応答します。アクセサーを定義しても、対応 するインスタンス変数が定義されていません。name =obj.name=('xyz')
name
bookattr_reader :book
bookinitializenew@book = p_book
26 行目) 私は常に、アクセサーはシンボルのみを受け入れると信じてきました。変数は可能ですが、関心は限られていることがわかりました。
7) setter メソッドtitle=が @title を作成しました。これは、インスタンス変数が単一のオブジェクトに属していることも示しています。他の言語と同様に、それらはクラスのすべてのインスタンスに属しているとしばしば信じています。この場合、@name は 6 行目で作成されたオブジェクトのみに属します。
8) getter メソッドtitleは @title の値に応答します。

class MyClass
    def title # line 34
        @book + ' (cheating !)'
    end
end

print '9) obj.title : '; p obj.title  

出力:

t.rb:34: warning: method redefined; discarding old title  
9) obj.title : "The Pickaxe (cheating !)"  

9) もちろん、アクセサ シンボルと対応するインスタンス変数の間には密接な相関関係があります。なぜなら、Ruby はバックグラウンドで、同じ名前のインスタンス変数を参照するメソッドを作成するからです。独自のゲッターとチートを定義できます。


クラス変数 (@@var、グローバル変数と同じくらい醜いものを嫌う人もいます) に加えて、クラスはインスタンス変数を持つこともできます。私はそれらをクラスインスタンス変数と呼びます:)。
class MyClass: Ruby はクラス Class の新しいインスタンスを割り当て、定数 MyClass を定義し、新しいインスタンスをその定数に割り当てます。したがって、MyClass は通常のオブジェクト (Class のインスタンス) であり、インスタンス変数を持つことができます。

if RUBY_VERSION[0..2] == '1.8'
    class Object
        def singleton_class
            class << self
                self
            end
        end
    end
end

class MyClass
    singleton_class.instance_eval do
        attr_accessor :counter
    end
    @counter = 0

    def initialize(p_book)
        @book = p_book
        self.class.counter += 1
    end
end

print '10) MyClass.singleton_methods  : '; p MyClass.singleton_methods
print '11) MyClass.instance_variables : '; p MyClass.instance_variables
obj = MyClass.new('Ruby')
print '12) [new] obj.book ', MyClass.counter, ': '; p obj.book
obj = MyClass.new('Metaprogramming')
print '13) [new] obj.book ', MyClass.counter, ': '; p obj.book  

出力:

t.rb:55: warning: method redefined; discarding old initialize
10) MyClass.singleton_methods  : ["counter", "counter="]
11) MyClass.instance_variables : ["@counter"]
12) [new] obj.book 1: "Ruby"
13) [new] obj.book 2: "Metaprogramming"  

ここでシングルトンメソッドの詳細: def `self.function` name とはどういう意味ですか?

(*) http://pragprog.com/book/ruby3/programming-ruby-1-9

于 2012-12-13T13:46:01.903 に答える
1

(あなたのコメントへの答え)

dog = 'dog'またString.new("dog")

dog = String.new の後、インスタンス dog のフィールド クラスはクラス String を指します。

class << dog
    puts "inside #{self}" #=> inside #<Class:#<String:0x007fb38a83a820>>
    def bark
        puts 'woof'
    end
end
dog.bark #=> "woof" 
p dog.singleton_methods #=> ["bark"]

class << dogorを使用するdef dog.barkと、Ruby は無名クラスを作成し、インスタンス dog のフィールド クラスはこの無名クラスを指し、そこから String を指します。def または define_method を使用してこのコンテキストで定義されたメソッドは、無名クラスのメソッド テーブルに入ります。

Ruby 1.9.2 で Object#singleton_class が導入されました。[つるはし] obj のシングルトン クラスを返し、必要に応じて作成します。(追記) に相当しclass << self; self endます。

Ruby プログラミング言語 (O'Reily) は、オブジェクト o の固有クラス [シングルトン クラス] を開くには、クラス << o を使用します。

だから、声に出して読む方法がわかりません。を好む人もいると読みましたo >> class。この奇妙な表現が何を意味するのかを理解する方法を見つけたのは、つい最近のことです。私は発音します:oから匿名クラスに移動します。

class << MyClass
    def dog
        puts 'dog as class method'
    end
end
MyClass.dog #=> dog as class method

同じことがクラスにも当てはまります。ではclass MyClass、Class のインスタンスとしての MyClass は、そのクラス Class へのポインタを持つオブジェクトです。def MyClass.some_methodまたはを使用するclass << MyClassと、Ruby は MyClass と Class の間に挿入される無名クラスを作成し、クラス メソッドがその中に入ります。

たぶん次のようなものです:「クラスから、シングルトンオブジェクトselfをインスタンス化します

はい、「クラス/オブジェクトから」匿名のシングルトン クラス/固有クラス/メタクラスに。しかし、私たちは自己をインスタンス化しません。Self (Smaltalk では、C++/Java では this) は、メッセージの受信者を指定する一種の予約語です。dog.bark: OO 言語では、メッセージの吠え声がオブジェクト dog に送信されると言います。メソッド内でbark、 self を dog に設定して、dog を参照できるようにします。これは、

o1 = MyClass.new; o2 = MyClass.new
o1.some_method; o2.some_method

some_method は、一般的な方法でレシーバーを参照できる必要があります。それは o1 か o2 か、これが self の目的です。

于 2012-12-14T02:12:56.583 に答える