25

我看到如下代码:

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 initialize以及attr_accessor它们如何啮合。

4

4 回答 4

27

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"
于 2013-05-20T18:34:18.400 回答
20

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

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

类和方法

现在我们准备创建我们自己的地址类。让我们从简单的开始。让我们从只包含“街道”字段的地址开始。

这是定义类的方式:

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

让我们来看看这个:

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

  • 通过在这个类中定义一个方法,我们将它与这个类关联起来。

  • 初始化方法是实际构造数据结构的方法。每个类都必须包含一个初始化方法。

@street 是一个对象变量。类似于哈希的键。@ 符号将@street 区分为对象变量。每次创建 Address 类的对象时,该对象都将包含一个 @street 变量。

让我们使用这个类来创建一个地址对象。

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

而已。地址现在是类地址的对象读取对象中的数据

假设我们要读取地址对象中的数据。为此,我们需要编写一个返回此数据的方法:

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

对象的一个​​在外部可见的属性称为属性。在这种情况下,街道是一个属性。特别是,它是一个可读属性。因为这种属性很常见,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."
                   

请注意,您可以放置​​空间 betten street 和 =。现在我们可以更改地址数据,我们可以简化初始化方法,并将街道默认为空字符串“”。

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


                   

这可能看起来不是很简单,但是当我们添加城市、州和邮政编码字段以及更多方法时,这将使类定义更简单一些。

现在,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
                   
于 2013-05-20T18:33:59.863 回答
6

我认为您将initialize其视为构造函数。准确地说,事实并非如此。默认构造函数是new类上的方法,initialize并由该方法调用。如果你不定义initialize,你仍然可以创建一个对象,new因为initialize不是构造函数本身。在这种情况下,默认值initialize什么也不做。如果您确实定义initialize了,那么它会在对象创建后立即调用。

说法@foo = ...attr_accessor :foo不同。前者为实例变量赋值@foo,而后者让你@foo 通过方法foo和访问foo=。没有后者,你仍然可以@foo通过直接描述so来访问。

于 2013-05-20T18:48:49.630 回答
-2

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

例如:

  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.

尽管我们已将值设置为 item,但我们无法对它做任何事情,因为实例变量在 ruby​​ 中是私有的。吸气剂代码:

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

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

于 2017-06-14T16:17:04.740 回答