我看到的代码如下:
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
以及它们如何相互作用。
答案 0 :(得分:22)
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"
答案 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
分配值,而后者允许您通过方法@foo
和foo
访问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可以让我们随时灵活地为实例变量提供值。