为什么 Rails' attr_getter 实际上是多余的

Why Rails' attr_getter is actually redundant

我正在 Rails' attr_accessor 上学习 Ruby 的实际功能。在下面的示例中,我知道它将生成“name”和“name=”方法。其中,我可以测试“name=”的实际效果,但是即使我去掉整行attr_accessor,也不影响我获取到“name”的参数值。换句话说,attr_getter实际上什么都不做。

但这在理论上是错误的,我该如何纠正这种错误的看法?

class HelloWorld
  attr_accessor :name

  def initialize(name = "Old name")   
    @name = name
  end

  def hello          
    puts "Hello, I am #{@name}"
  end

  def intro
    puts "I name is #{@name}"
  end
end

user = HelloWorld.new()           
user.name = "New name"
user.hello                        #=> Hello, I am New name
user.intro                        #=> I name is New name

正如评论中提到的那样,它与 Rails 无关,它是 Ruby 核心的一部分。

@name 只是一个实例变量,仅在 HelloWorld 的实例中可用。当您删除 attr_accessor :name 时,您将无法从外部读取或写入 @name(实际上您可以使用 instance_variable_get and instance_variable_set。但您真的需要它吗?)

class HelloWorld
  def initialize(name = "Old name")
    @name = name
  end
end

hello_world = HelloWorld.new

你看不懂

hello_world.name
undefined method `name' for #<HelloWorld:0x00007f3125ea51e8 @name="Old name"> (NoMethodError)

你不会写的

hello_world.name= 'New name'
undefined method `name=' for #<HelloWorld:0x00007f3125ea51e8 @name="Old name"> (NoMethodError)

由您决定是否需要授予对变量的访问权限。 如果您只需要 reader,请使用 attr_reader. If you want to write it use attr_writer。如果两者都需要,请保持原样 attr_accessor.

取决于你。
这在理论上并没有错。实际上,我们可以选择如何运行程序代码。我们在程序代码中使用 OOP 概念。该程序的代码在逻辑上是正确的。 我认为您是在说您的代码是正确的。

class HelloWorld
   def setName(name = "Old name")
        @name = name
   end
   def hello
        puts "Hello, I am #{@name}"
   end
   def intro
        puts "I name is #{@name}"
   end
end
keaton = HelloWorld.new()
keaton.setName("New name")
keaton.hello
keaton.intro

#OUTPUT :
#Hello, I am New name
#I name is New name

您知道 属性 中其他语言的 get 和 set 方法。 get方法returns变量的值和set赋值给name变量

例如:在 C# 中,在 属性

中获取 set 方法
public class HelloWorld
{
    private int _name;
    public int Age
    {
        get { return _name; }
        set { _name = value; }
    }
}   

ruby

中的逻辑相同
class HelloWorld

    attr_accessor :name

    def initialize
        @name = name
    end

end

我想我明白了,简单地说:

  • 原来getter和setter定义实例方法“name and name=" 分别.
# getter
def name                 
     @name
end

# setter
def name=(value)    
     @name = value
end
  • def name不是def self.name,所以不是 class 方法。
  • attr_accessor 允许 class HelloWorld 及其新实例 使用实例方法 "name and name=".
  • 方法“name and name=”的默认值是指定的 初始化的实例变量@name.
  def initialize(name = "No name")
    @name = name
  end
  • 方法“hello”和“intro”不能重新赋值(就像setter可以做的),但可以有更丰富的输出结果,比如句子。