web-dev-qa-db-ja.com

1つのクラスでのattr_accessorと初期化メソッドの混在

次のようなコードが表示されます:

_class Person
  def initialize(name)
    @name = name
  end
end
_

これにより、_person = Person.new_などの処理が可能になり、他のメソッドのようにクラスの他の場所で_@name_を使用できるようになることを理解しています。次に、私は次のようなコードを見ました:

_class Person
  attr_accessor :name
end

...

person = Person.new
person.name = "David"
_

私はこれら2つの方法のメッシュで途方に暮れています。 def initialize(name)の特定の用途は何ですか? _attr_accessor_を使用すると、読み取りと書き込みが可能になります。つまり、これらは2つの別々の方法であることを意味します。はい? _def initialize_と_attr_accessor_、およびそれらがどのようにかみ合うかを明確にしたい。

22
David

initializeおよびattr_accessor相互に何の関係もありません。 attr_accessor :nameは、いくつかのメソッドを作成します。

def name
  @name
end

def name=(val)
  @name = val
end

オブジェクトの作成時に名前を設定する場合は、イニシャライザで行うことができます。

def initialize(name)
  @name = name
  # or
  # self.name = name
end

しかし、そうする必要はありません。作成後、後で名前を設定できます。

p = Person.new
p.name = "David"
puts p.name # >> "David"
25

これがあなたが探している答えです Classes and methods 。注意深く読んでください。

ここにリンクからの良いドキュメントがあります:

クラスとメソッド

これで、独自のAddressクラスを作成する準備ができました。簡単に始めましょう。 「番地」フィールドのみを含む住所から始めましょう。

これは、クラスを定義する方法です。

class Address
    def initialize(street)  
        @street = street 
    end
end

これを見てみましょう:

  • Classキーワードはクラスを定義します。

  • このクラス内でメソッドを定義することにより、このクラスに関連付けます。

  • Initializeメソッドは、実際にデータ構造を構築するものです。すべてのクラスには、initializeメソッドが含まれている必要があります。

@streetはオブジェクト変数です。ハッシュのキーに似ています。 @記号は、@ streetをオブジェクト変数として区別します。クラスAddressのオブジェクトを作成するたびに、このオブジェクトには@street変数が含まれます。

このクラスを使用して、アドレスオブジェクトを作成しましょう。

address = Addres.new("23 St George St.")  

それでおしまい。 addressはクラスAddressのオブジェクトですオブジェクト内のデータの読み取り

アドレスオブジェクトのデータを読み取りたいとします。これを行うには、このデータを返すメソッドを記述する必要があります。

class Address
    def initialize(street)   
        @street = street 
    end

    # Just return @street
    def street
        @street
    end
end

メソッドAddress#streetを使用すると、住所の通りを読み取ることができます。 IRBで:

>> address.street 
=> "23 St George St."

外部から見えるオブジェクトのプロパティは属性と呼ばれます。この場合、street isが属性です。特に、読み取り可能な属性です。この種の属性は非常に一般的であるため、Rubyはattr_readerキーワードを介してショートカットを提供します。

class Address
    attr_reader :street
    def initialize(street)   
        @street = street 
    end
end

オブジェクト内のデータの変更

オブジェクトのデータを変更するメソッドを定義することもできます。

class Address
    attr_reader :street
    def initialize(street)  
        @street = street 
    end
    def street=(street)
        @street = street
    end
end

Rubyは、street =メソッドを使用するのがかなり賢明です。

`address.street = "45 Main St`."

ストリートと=にスペースを置くことができることに注意してください。住所データを変更できるようになったので、initializeメソッドを簡略化し、ストリートのデフォルトを空の文字列 ""にするだけです。

class Address
    attr_reader :street
    def initialize
        @street = ""
    end
    def street=(street)
        @street = street  
    end
end

address = Address.new
address.street = "23 St George St."

これは単純化のようには見えないかもしれませんが、city、state、およびZipフィールド、およびより多くのメソッドを追加すると、クラス定義が少し単純になります。

現在、ストリートは書き込み可能な属性でもあります。前と同じように、attr_writerを使用してそのように宣言できます。

class Address
    attr_reader :street
    attr_writer :street  
    def initialize
        @street = ""
    end
end

データへのアクセス

多くの場合、読み取りと書き込みの両方が可能な属性があります。 Rubyでは、これらをattr_accessorと一緒にまとめることができます。これらは「アクセス可能な属性」と呼ばれると思いますが、そのように呼ばれることはありません。

class Address
    attr_accessor :street  
    def initialize
        @street = ""
    end
end

この知識があれば、アドレス帳の構造全体を簡単に定義できます。結局のところ、attr_accessorとその仲間はすべて複数の引数を受け入れます。

class Address
    attr_accessor :street, :city, :state, :Zip  
    def initialize
        @street = @city = @state = @Zip = ""
    end
end
17
Arup Rakshit

initializeはコンストラクターだと思います。正確には、そうではありません。デフォルトのコンストラクタはクラスのnewメソッドであり、initializeはそのメソッドによって呼び出されます。 initializeを定義しない場合でも、new自体はコンストラクターではないため、initializeを使用してオブジェクトを作成できます。その場合、デフォルトのinitializeは何もしません。 initializeを定義すると、オブジェクトの作成直後に呼び出されます。

ステートメント@foo = ...attr_accessor :fooは異なります。前者はインスタンス変数@fooに値を割り当てますが、後者はメソッドfooおよび@fooを介してfoo=にアクセスできます。後者がなくても、直接記述することで@fooにアクセスできます。

6
sawa