在一个类中混合attr_accessor和initialize方法

时间:2013-05-20 18:28:59

标签: ruby initialization 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"

我对这两种方法网格感到茫然。 def initialize(name)的具体用途是什么?我想attr_accessor允许我读写。这意味着它们是两种不同的方法。是?想要澄清def initializeattr_accessor以及它们如何相互作用。

4 个答案:

答案 0 :(得分:22)

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

答案 1 :(得分:15)

以下是您正在寻找的答案Classes and methods。仔细阅读。

这是一个很好的文档链接:

课程和方法

现在我们已经准备好创建我们自己的Address类了。让我们开始吧。让我们从一个只包含“街道”字段的地址开始。

这就是你定义一个类的方法:

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

让我们来看看:

  • class关键字定义了一个类。

  • 通过在此类中定义方法,我们将其与此类关联。

  • 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是一个属性。特别是,它是一个可读属性。因为这种属性很常见,所以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`."

请注意,您可以在街道和=之间添加空格。现在我们可以更改地址数据,我们可以简化初始化方法,并将它简单地将街道默认为空字符串“”。

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字段以及更多方法时,这将使类定义更简单。

现在,street也是一个可写属性。和以前一样,您可以使用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

答案 2 :(得分:5)

我认为你认为initialize是一个构造函数。确切地说,事实并非如此。默认构造函数是类上的new方法,并且该方法调用initialize。如果您未定义initialize,则仍可以使用new创建对象,因为initialize不是构造函数本身。在这种情况下,默认initialize不执行任何操作。如果您确实定义了initialize,那么在创建对象后立即调用它。

声明@foo = ...attr_accessor :foo不同。前者为实例变量@foo分配值,而后者允许您通过方法@foofoo访问foo=。如果没有后者,您仍然可以通过直接描述来访问@foo

答案 3 :(得分:-1)

与C ++不同,Ruby中的Java实例变量默认为私有(部分可以通过使用a.instance_variable_get来访问它们:@x)

例如:

docker-php-ext-enable xdebug

虽然我们已将值设置为item但我们无法对其执行任何操作,因为instace变量在ruby中是私有的。 getter的代码:

  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.

使用getter将确保item.task返回它的值 使用setter可以让我们随时灵活地为实例变量提供值。