Intermingling attr_accessor and an initialize method in one class

后端 未结 4 1450
梦毁少年i
梦毁少年i 2021-01-30 02:59

I see code like:

class Person
  def initialize(name)
    @name = name
  end
end

I understand this allows me to do things like person = Pe

相关标签:
4条回答
  • 2021-01-30 03:16

    Here is the answer you are looking for Classes and methods. Read it carefully.

    Here is a good documentation from the link:

    Classes and methods

    Now we are ready to create our very own Address class. Let's start simple. Let's start with an address that only contains the "street" field.

    This is how you define a class:

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

    Let's go through this:

    • The class keyword defines a class.

    • By defining a method inside this class, we are associating it with this class.

    • The initialize method is what actually constructs the data structure. Every class must contain an initialize method.

    @street is an object variable. Similar to the keys of a hash. The @ sign distinguishes @street as an object variable. Every time you create an object of the class Address, this object will contain a @street variable.

    Let's use this class to create an address object.

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

    That's it. address is now an object of the class Address Reading the data in an object

    Suppose that we want to read the data in the address object. To do this, we need to write a method that returns this data:

    class Address
        def initialize(street)   
            @street = street 
        end
    
        # Just return @street
        def street
            @street
        end
    end
    

    Now the method Address#street lets you read the street of the address. In irb:

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

    A property of an object, which is visible outside, is called an attribute. In this case, street is is an attribute. In particular, it is a readable attribute. Because this kind of attribute is very common, Ruby offers you a shortcut through the attr_reader keyword:

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

    Changing the data in an object

    We can also define a method to change the data in an object.

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

    Ruby is pretty smart in its use of the street= method:

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

    Notice that you can put spaces betten street and =. Now that we can change the address data, we can simplify the initialize method, and have it simply default the street to the empty string "".

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

    This might not seem like much of a simplification, but when we add the city, state and zip fields, and more methods this will make the class definition a bit simpler.

    Now, street is also a writable attribute. As before, you can declare it as such with attr_writer:

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

    Accessing data

    Very often, you have attributes that are both readable and writable attributes. Ruby lets you lump these together with attr_accessor. I guess these would be called "accessible attributes", but I have never seen them be called that.

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

    With this knowledge, it is now easy to define the entire addressbook structure. As it turns out, attr_accessor and friends all accept multiple arguments.

    class Address
        attr_accessor :street, :city, :state, :zip  
        def initialize
            @street = @city = @state = @zip = ""
        end
    end
    
    0 讨论(0)
  • 2021-01-30 03:23

    I think you consider initialize as a constructor. To be precise, it is not. The default constructor is the new method on the class, and initialize is called by that method. If you do not define initialize, you can still create an object with new because initialize is not the constructor itself. In that case, the default initialize does nothing. If you do define initialize, then that is called right after the object creation.

    The statement @foo = ... and attr_accessor :foo are different. The former assigns a value to the instance variable @foo, whereas the latter lets you access @foo via methods foo and foo=. Without the latter, you can still access @foo by directly describing so.

    0 讨论(0)
  • 2021-01-30 03:23

    Unlike C++,Java instance variables in Ruby are private by default(partially as they can be accessed by using a.instance_variable_get :@x)

    eg:

      class Dda
        def initialize task
            @task = task
            @done = false
        end
      end
    item = Dda.new "Jogging" # This would call the initializer and task = Jogging would
    be set for item
    item.task # would give error as their is no function named task to access the instance
    variable.
    

    Although we have set the value to item but we won't be able to do anything with it as instace variables are private in ruby. code for getter:

    def task
      @task
    end
    #for getter
    def task=task
       @task = task
    end
    

    Using getter would ensure that item.task returns it's value And using setter gives us the flexibility to provide values to instance variables at any time.

    0 讨论(0)
  • 2021-01-30 03:24

    initialize and attr_accessor have nothing to do with each other. attr_accessor :name creates a couple of methods:

    def name
      @name
    end
    
    def name=(val)
      @name = val
    end
    

    If you want to set name upon object creation, you can do it in the initializer:

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

    But you don't have to do that. You can set name later, after creation.

    p = Person.new
    p.name = "David"
    puts p.name # >> "David"
    
    0 讨论(0)
提交回复
热议问题