什么是Ruby中的attr_accessor?

我很难理解Ruby中的attr_accessor 。 谁可以给我解释一下这个?


#1楼

简单地说attr-accessor为指定的属性创建gettersetter方法


#2楼

我认为新Rubyists /程序员(比如我自己)困惑的一部分是:

“为什么我不能告诉它具有任何给定属性的实例(例如,名称)并且一举给出该属性一个值?”

更广泛一点,但这就是它为我点击的方式:

鉴于:

class Person
end

我们没有将Person定义为可以具有名称或任何其他属性的东西

那么如果我们那么:

baby = Person.new

......并试着给他们起个名字......

baby.name = "Ruth"

我们得到一个错误,因为在Rubyland中,Person类的对象不是与“名称”相关联或能够拥有“名称”的东西......

但是我们可以使用任何给定的方法(参见前面的答案)作为一种方式来说,“Person类( baby )的实例现在可以有一个名为'name'的属性,因此我们不仅有一种语法上的获取方式并设置该名称,但我们这样做是有道理的。“

再次,从一个稍微不同和更一般的角度来看这个问题,但我希望这有助于下一个类人物的实例,他们找到了通往这个线程的方法。


#3楼

简单地说,它将为类定义一个setter和getter。

注意

attr_reader :v is equivalant to 
def v
  @v
end

attr_writer :v is equivalant to
def v=(value)
  @v=value
end

所以

attr_accessor :v which means 
attr_reader :v; attr_writer :v 

是等价的,为类定义一个setter和getter。


#4楼

如果您熟悉OOP概念,则必须熟悉getter和setter方法。 attr_accessor在Ruby中做同样的事情。

一般方式的吸气剂和塞特犬

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

person = Person.new
person.name = 'Eshaan'
person.name # => "Eshaan"

二传法

def name=(val)
  @name = val
end

吸气方法

def name
  @name
end

Ruby中的Getter和Setter方法

class Person
  attr_accessor :name
end

person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"

#5楼

为此模块定义命名属性,其名称为symbol.id2name,创建实例变量(@name)以及相应的访问方法以读取它。 还创建一个名为name =的方法来设置属性。

module Mod
  attr_accessor(:one, :two)
end
Mod.instance_methods.sort   #=> [:one, :one=, :two, :two=]

#6楼

我也遇到了这个问题,并为这个问题写了一个冗长的答案。 已经有一些很好的答案,但任何寻求更多澄清的人,我希望我的答案可以帮助

初始化方法

Initialize允许您在创建实例时将数据设置为对象的实例,而不是每次创建类的新实例时都必须在代码中的单独行上设置它们。

class Person
  attr_accessor :name

  def initialize(name)
    @name = name
  end


  def greeting
    "Hello #{@name}"
  end
end

person = Person.new("Denis")
puts person.greeting

在上面的代码中,我们使用initialize方法设置名称“Denis”,方法是将Dennis传递给Initialize中的参数。 如果我们想在没有initialize方法的情况下设置名称,我们可以这样做:

class Person
  attr_accessor :name

  # def initialize(name)
  #     @name = name
  # end

  def greeting
    "Hello #{name}"
  end
end

person = Person.new
person.name = "Dennis"
puts person.greeting

在上面的代码中,我们通过使用person.name调用attr_accessor setter方法来设置名称,而不是在初始化对象时设置值。

执行此操作的两种“方法”,但初始化节省了我们的时间和代码行。

这是初始化的唯一工作。 您无法调用初始化作为方法。 要实际获取实例对象的值,您需要使用getter和setter(attr_reader(get),attr_writer(set)和attr_accessor(both))。 有关这些的详细信息,请参见下文。

Getters,Setters(attr_reader,attr_writer,attr_accessor)

Getters,attr_reader:getter的全部目的是返回特定实例变量的值。 请访问下面的示例代码,了解相关信息。

class Item

  def initialize(item_name, quantity)
    @item_name = item_name
    @quantity = quantity
  end

  def item_name
    @item_name
  end

  def quantity
     @quantity
  end
end

example = Item.new("TV",2)
puts example.item_name
puts example.quantity

在上面的代码中,您在Item“example”的实例上调用方法“item_name”和“quantity”。 “puts example.item_name”和“example.quantity”将返回(或“获取”)传递给“示例”的参数的值,并将它们显示在屏幕上。

幸运的是,在Ruby中有一种固有的方法可以让我们更简洁地编写这段代码; attr_reader方法。 见下面的代码;

class Item

attr_reader :item_name, :quantity

  def initialize(item_name, quantity)
    @item_name = item_name
    @quantity = quantity
  end

end

item = Item.new("TV",2)
puts item.item_name
puts item.quantity

这种语法的工作方式完全相同,只为它节省了六行代码。 想象一下,如果你还有5个属于Item类的状态? 代码会很快变长。

Setters,attr_writer:首先使用setter方法让我感到惊讶的是,在我看来,它似乎与initialize方法执行相同的功能。 下面我根据我的理解解释差异;

如前所述,initialize方法允许您在创建对象时设置对象实例的值。

但是,如果您希望稍后在创建实例后设置值,或者在初始化实例后更改它们,该怎么办? 这将是您使用setter方法的场景。 这是不同的。 最初使用attr_writer方法时,不必“设置”特定状态。

下面的代码是使用setter方法为Item类的此实例声明值item_name的示例。 请注意,我们继续使用getter方法attr_reader,以便我们可以获取值并将它们打印到屏幕上,以防您想要自己测试代码。

class Item

attr_reader :item_name

  def item_name=(str)
    @item_name = (str)
  end

end

下面的代码是使用attr_writer再次缩短代码并节省时间的示例。

class Item

attr_reader :item_name
attr_writer :item_name

end

item = Item.new
puts item.item_name = "TV"

下面的代码重复上面的初始化示例,我们使用initialize在创建时设置item_name的对象值。

class Item

attr_reader :item_name

  def initialize(item_name)
    @item_name = item_name
  end

end

item = Item.new("TV")
puts item.item_name

attr_accessor:执行attr_reader和attr_writer的功能,为您节省一行代码。


#7楼

没有任何代码的简单解释

以上大多数答案都使用代码。 这个解释试图通过类比/故事来回答它而不使用任何:

外部各方无法访问内部中央情报局的秘密

  • 让我们想象一个真正秘密的地方:中央情报局。 除了中央情报局内部的人员,没有人知道中情局正在发生什么。 换句话说,外部人员无法访问中央情报局的任何信息。 但是因为拥有一个完全保密的组织并不是一件好事,所以某些信息可以提供给外界 - 只有CIA当然希望每个人都知道的事情:例如中央情报局局长,这个部门的环保程度如何所有其他政府部门等。其他信息:例如谁是伊拉克或阿富汗的秘密特工 - 这些类型的事情可能仍然是未来150年的秘密。

  • 如果您在CIA之外,您只能访问它向公众提供的信息。 或者,要使用CIA说法,您只能访问“已清除”的信息。

  • 美国中央情报局希望向中央情报局以外的公众提供的信息称为: 属性。

读写属性的含义:

  • 在CIA的情况下,大多数属性是“只读”。 这意味着如果你是中情局外部的一方,你可以问: “谁是中央情报局局长?” 你会得到一个直接的答案。 但是,“只读”属性无法做到的是在CIA中进行更改。 例如,你不能打电话,突然决定你想让金·卡戴珊成为导演,或者你希望帕丽斯·希尔顿成为总司令。

  • 如果属性为您提供“写入”访问权限,那么即使您在外面,也可以根据需要进行更改。 否则,你唯一能做的就是阅读。

    换句话说,访问者允许您对不允许外部人员进入的组织进行查询或进行更改,具体取决于访问者是读取访问者还是写入访问者。

类中的对象可以轻松地相互访问

  • 另一方面,如果您已经 CIA 内部 ,那么您可以轻松地在喀布尔召集您的中央情报局特工,因为这些信息很容易获得,因为您已经在里面。 但是,如果您不在 CIA 之外 ,您将无法获得访问权限:您将无法知道他们是谁(读访问权限),并且您将无法更改其任务(写访问权限)。

与类完全相同的事情以及访问其中的变量,属性和方法的能力。 HTH! 有任何问题,请询问,我希望我能澄清一下。


#8楼

attr_accessor与其他文件的主要功能是从其他文件访问数据的功能。
所以你通常会有attr_reader或attr_writer,但好消息是Ruby允许你将这两者与attr_accessor结合起来。 我认为这是我的方法,因为它更圆润或多功能。 另外,请记住,在Rails中,这被消除了,因为它在后端为您完成。 所以换句话说:你最好使用attr_acessor而不是其他两个,因为你不必担心具体,访问者会覆盖它。 我知道这更多是一般性的解释,但它帮助我作为初学者。

希望这有帮助!


#9楼

属性和访问器方法

属性是可以从对象外部访问的类组件。 它们在许多其他编程语言中称为属性。 可以使用“点表示法”访问它们的值,如object_name.attribute_name中所示。 与Python和其他一些语言不同,Ruby不允许直接从对象外部访问实例变量。

class Car
  def initialize
    @wheels = 4  # This is an instance variable
  end
end

c = Car.new
c.wheels     # Output: NoMethodError: undefined method `wheels' for #<Car:0x00000000d43500>

在上面的例子中,c是Car类的实例(对象)。 我们尝试从对象外部读取wheel实例变量的值,但未成功。 发生的事情是Ruby试图在c对象中调用一个名为wheels的方法,但是没有定义这样的方法。 简而言之,object_name.attribute_name尝试在对象中调用名为attribute_name的方法。 要从外部访问wheels变量的值,我们需要通过该名称实现一个实例方法,该方法将在调用时返回该变量的值。 这被称为存取方法。 在通用编程上下文中,从对象外部访问实例变量的常用方法是实现访问器方法,也称为getter和setter方法。 getter允许从外部读取类中定义的变量的值,并且setter允许从外部写入它。

在下面的示例中,我们将getter和setter方法添加到Car类,以从对象外部访问wheel变量。 这不是定义getter和setter的“Ruby方式”; 它仅用于说明getter和setter方法的作用。

class Car
  def wheels  # getter method
    @wheels
  end

  def wheels=(val)  # setter method
    @wheels = val
  end
end

f = Car.new
f.wheels = 4  # The setter method was invoked
f.wheels  # The getter method was invoked
# Output: => 4

上面的示例有效,类似的代码通常用于在其他语言中创建getter和setter方法。 但是,Ruby提供了一种更简单的方法:三种内置方法,称为attr_reader,attr_writer和attr_acessor。 attr_reader方法使实例变量可以从外部读取,attr_writer使其可写,而attr_acessor使其可读和可写。

上面的例子可以像这样重写。

class Car
  attr_accessor :wheels
end

f = Car.new
f.wheels = 4
f.wheels  # Output: => 4

在上面的示例中,wheels属性将从对象外部读取和写入。 如果不是attr_accessor,我们使用attr_reader,它将是只读的。 如果我们使用attr_writer,它将是只写的。 这三种方法本身不是getter和setter,但是在调用时,它们为我们创建了getter和setter方法。 它们是动态(以编程方式)生成其他方法的方法; 那叫做元编程。

第一个(更长的)示例不使用Ruby的内置方法,只应在getter和setter方法中需要其他代码时使用。 例如,在为实例变量赋值之前,setter方法可能需要验证数据或进行一些计算。

通过使用instance_variable_get和instance_variable_set内置方法,可以从对象外部访问(读取和写入)实例变量。 然而,这很少是合理的,通常是一个坏主意,因为绕过封装往往会造成各种各样的破坏。


#10楼

理解它的另一种方法是通过使用attr_accessor来确定它消除了哪些错误代码。

例:

class BankAccount    
  def initialize( account_owner )
    @owner = account_owner
    @balance = 0
  end

  def deposit( amount )
    @balance = @balance + amount
  end

  def withdraw( amount )
    @balance = @balance - amount
  end
end

可以使用以下方法:

$ bankie = BankAccout.new("Iggy")
$ bankie 
$ bankie.deposit(100)
$ bankie.withdraw(5)

以下方法抛出错误:

$ bankie.owner     #undefined method `owner'... 
$ bankie.balance   #undefined method `balance'...

owner技术上讲, ownerbalance不是一种方法 ,而是一种属性。 BankAccount类没有def ownerdef balance 。 如果是,则可以使用以下两个命令。 但这两种方法都不存在。 但是,您可以访问属性,就像您通过attr_accessor 访问方法attr_accessor因此, attr_accessor这个词 。 属性。 访问。 它访问属性,就像访问方法一样。

添加attr_accessor :balance, :owner允许您读取和写入balanceowner “方法”。 现在您可以使用最后两种方法。

$ bankie.balance
$ bankie.owner

#11楼

总结属性访问器aka attr_accessor为您提供了两种免费方法。

就像在Java中一样,它们被称为getter和setter。

很多答案都显示了很好的例子,所以我只是简短一点。

#the_attribute

#the_attribute =

在旧的ruby文档中,哈希标记#表示方法。 它还可以包含类名前缀... MyClass#my_method


#12楼

基本上他们伪造了可公开访问的数据属性,Ruby没有。


#13楼

attr_accessor 只是一种方法 。 (该链接应提供有关其工作原理的更多信息 - 查看生成的方法对,教程应向您展示如何使用它。)

诀窍是class 不是 Ruby中的定义 (它只是C ++和Java等语言中的“定义”),但它是一个评估表达式 。 在此评估期间,当调用attr_accessor方法时,该方法又修改当前类 - 记住隐式接收器: self.attr_accessor ,其中self是此时的“open”类对象。

attr_accessor和朋友的需求是:

  1. 与Smalltalk一样,Ruby不允许在该对象的方法1之外访问实例变量。 也就是说,实例变量不能以xy形式访问,就像在Java甚至Python中常见的那样。 在Ruby中, y始终被视为要发送的消息(或“要调用的方法”)。 因此, attr_*方法创建了包装器,它通过动态创建的方法代理实例@variable访问。

  2. 锅炉很糟糕

希望这能澄清一些细节。 快乐的编码。


1这并非严格正确,并且有一些“技术” ,但“公共实例变量”访问没有语法支持。


#14楼

attr_accessor非常简单:

attr_accessor :foo

是一个快捷方式:

def foo=(val)
  @foo = val
end

def foo
  @foo
end

它只不过是一个对象的getter / setter


#15楼

它只是一个为实例变量定义getter和setter方法的方法。 一个示例实现是:

def self.attr_accessor(*names)
  names.each do |name|
    define_method(name) {instance_variable_get("@#{name}")} # This is the getter
    define_method("#{name}=") {|arg| instance_variable_set("@#{name}", arg)} # This is the setter
  end
end

#16楼

attr_accessor (如@pst所述)只是一种方法。 它的作用是为您创造更多方法。

所以这里的代码如下:

class Foo
  attr_accessor :bar
end

相当于这段代码:

class Foo
  def bar
    @bar
  end
  def bar=( new_value )
    @bar = new_value
  end
end

您可以在Ruby中自己编写这种方法:

class Module
  def var( method_name )
    inst_variable_name = "@#{method_name}".to_sym
    define_method method_name do
      instance_variable_get inst_variable_name
    end
    define_method "#{method_name}=" do |new_value|
      instance_variable_set inst_variable_name, new_value
    end
  end
end

class Foo
  var :bar
end

f = Foo.new
p f.bar     #=> nil
f.bar = 42
p f.bar     #=> 42

#17楼

假设你有一个Person

class Person
end

person = Person.new
person.name # => no method error

显然我们从未定义方法name 。 我们这样做。

class Person
  def name
    @name # simply returning an instance variable @name
  end
end

person = Person.new
person.name # => nil
person.name = "Dennis" # => no method error

啊哈,我们可以读取名称,但这并不意味着我们可以指定名称。 这是两种不同的方法。 前者称为读者 ,后者称为作家 。 我们还没有创作作家,所以让我们这样做。

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

person = Person.new
person.name = 'Dennis'
person.name # => "Dennis"

真棒。 现在我们可以使用reader和writer方法编写和读取实例变量@name 。 除此之外,经常这样做,为什么每次浪费时间写这些方法呢? 我们可以做得更轻松。

class Person
  attr_reader :name
  attr_writer :name
end

即使这样也会重复。 当你想要读者和作家都只使用访问者!

class Person
  attr_accessor :name
end

person = Person.new
person.name = "Dennis"
person.name # => "Dennis"

以同样的方式工作! 并猜测:我们的person对象中的实例变量@name将被设置,就像我们手动完成时一样,因此您可以在其他方法中使用它。

class Person
  attr_accessor :name

  def greeting
    "Hello #{@name}"
  end
end

person = Person.new
person.name = "Dennis"
person.greeting # => "Hello Dennis"

而已。 为了理解attr_readerattr_writerattr_accessor方法如何为您实际生成方法,请阅读其他答案,书籍,ruby文档。


#18楼

嗯。 很多好的答案。 这是我的几美分。

  • attr_accessor是一个简单的方法,可以帮助我们在清洗(DRY-ING)重复getter and setter方法。

  • 这样我们就可以更专注于编写业务逻辑而不用担心setter和getter。


#19楼

我是ruby的新手,不得不理解以下的怪异。 未来可能会帮助别人。 最后,如上所述,其中2个函数(def myvar,def myvar =)都隐式访问@myvar,但这些方法可以被本地声明覆盖。

class Foo
  attr_accessor 'myvar'
  def initialize
    @myvar = "A"
    myvar = "B"
    puts @myvar # A
    puts myvar # B - myvar declared above overrides myvar method
  end

  def test
    puts @myvar # A
    puts myvar # A - coming from myvar accessor

    myvar = "C" # local myvar overrides accessor
    puts @myvar # A
    puts myvar # C

    send "myvar=", "E" # not running "myvar =", but instead calls setter for @myvar
    puts @myvar # E
    puts myvar # C
  end
end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值