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

Dav*_*vid 22 ruby initialization accessor

我看到代码如下:

class Person
  def initialize(name)
    @name = name
  end
end
Run Code Online (Sandbox Code Playgroud)

我明白这一点让我做这样的事情person = Person.new,并用@name在我的课像其他方法中的别处.然后,我看到代码如下:

class Person
  attr_accessor :name
end

...

person = Person.new
person.name = "David"
Run Code Online (Sandbox Code Playgroud)

我只是对这两种方法网格感到茫然.有什么特别的用途def initialize(name)?我想attr_accessor允许我读写.这意味着它们是两种不同的方法.是?希望在澄清def initializeattr_accessor他们如何网状.

Ser*_*sev 24

initialize并且attr_accessor彼此无关.attr_accessor :name创建了几种方法:

def name
  @name
end

def name=(val)
  @name = val
end
Run Code Online (Sandbox Code Playgroud)

如果要在创建对象时设置名称,可以在初始化程序中执行此操作:

def initialize(name)
  @name = name
  # or
  # self.name = name
end
Run Code Online (Sandbox Code Playgroud)

但你不必这样做.您可以在创建后稍后设置名称.

p = Person.new
p.name = "David"
puts p.name # >> "David"
Run Code Online (Sandbox Code Playgroud)


Aru*_*hit 15

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

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

类和方法

现在我们准备创建自己的Address类了.让我们开始吧.让我们从一个只包含"street"字段的地址开始.

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

class Address
    def initialize(street)  
        @street = street 
    end
end
Run Code Online (Sandbox Code Playgroud)

我们来看看:

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

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

  • initialize方法实际上是构造数据结构的方法.每个类都必须包含一个initialize方法.

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

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

address = Addres.new("23 St George St.")  
Run Code Online (Sandbox Code Playgroud)

而已.address现在是类Address的对象读取对象中的数据

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

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

    # Just return @street
    def street
        @street
    end
end
Run Code Online (Sandbox Code Playgroud)

现在使用Address#street方法可以读取地址的街道.在irb:

>> address.street 
=> "23 St George St."
Run Code Online (Sandbox Code Playgroud)

在外部可见的对象的属性称为属性.在这种情况下,street是一个属性.特别是,它是一个可读属性.因为这种属性很常见,所以Ruby通过attr_reader关键字为您提供了一个快捷方式:

class Address
    attr_reader :street
    def initialize(street)   
        @street = street 
    end
end
Run Code Online (Sandbox Code Playgroud)

更改对象中的数据

我们还可以定义一种方法来更改对象中的数据.

class Address
    attr_reader :street
    def initialize(street)  
        @street = street 
    end
    def street=(street)
        @street = street
    end
end
Run Code Online (Sandbox Code Playgroud)

Ruby在使用street =方法时非常聪明:

`address.street = "45 Main St`."
Run Code Online (Sandbox Code Playgroud)

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

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."
Run Code Online (Sandbox Code Playgroud)

这似乎不是简化,但是当我们添加city,state和zip字段以及更多方法时,这将使类定义更简单一些.

现在,street也是一个可写属性.和以前一样,您可以使用attr_writer声明它:

class Address
    attr_reader :street
    attr_writer :street  
    def initialize
        @street = ""
    end
end
Run Code Online (Sandbox Code Playgroud)

访问数据

通常,您具有可读和可写属性的属性.Ruby允许你将这些与attr_accessor混为一谈.我想这些将被称为"可访问属性",但我从未见过它们被称为"可访问属性".

class Address
    attr_accessor :street  
    def initialize
        @street = ""
    end
end
Run Code Online (Sandbox Code Playgroud)

有了这些知识,现在很容易定义整个地址簿结构.事实证明,attr_accessor和朋友都接受多个参数.

class Address
    attr_accessor :street, :city, :state, :zip  
    def initialize
        @street = @city = @state = @zip = ""
    end
end
Run Code Online (Sandbox Code Playgroud)

  • 请在答案中包含实际内容,而不是仅提供链接.仅限链接的答案是不受欢迎的,因为(a)答案不能独立存在,(b)如果链接发生故障,它会比无用的更糟糕. (3认同)
  • 好的!给:) (3认同)

saw*_*awa 6

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

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