Ruby:有没有办法直接访问(和改变)成员变量?

时间:2017-10-11 13:33:44

标签: ruby

我是ruby(和OOP最佳实践)的新手,我目前正在进行一些涉及课程的练习。其中一个让我制作一个字典,将“关键字”映射到它们的“定义”。以下是简化版本:

class Dictionary
  attr_accessor :entries, :keywords

  def initialize(opts = {})
    @entries = opts
    @keywords = opts.keys.sort
  end
end

无论如何,我有一个关于在类实现中改变成员变量值的问题。下面我有一个实例方法的例子,我需要更新@entries和@keywords的值。

def add(entry)
    if entry.instance_of?(Hash)
      @entries = @entries.merge!(entry)
    else
      @entries = entries.merge!({entry => nil})
    end
    @keywords = @entries.keys.sort
  end

在上面的例子中,我通过调用'='运算符来使用public setter方法 这有一些轻微的性能缺陷,因为我在评估r值时创建了一个新的Hash。

我知道在访问变量实例时通常最好使用setter,但我想知道是否有可能(即使不建议)在不使用setter的情况下更改类的成员变量?例如,在像python这样的语言中,如果不使用getter / setter,可以在成员变量上调用成员函数来改变其值。然而,在ruby中,似乎需要获取getter和setter(除非我弄错了)。我想也许有一种方法可以实现一个getter,因为它返回对成员变量的引用,所以它的行为就像直接访问一样?我想象的方式,结果将看起来像这样一个直观的观点:

 def add(entry)
    if entry.instance_of?(Hash)
      @entries.merge!(entry)
    else
      @entries.merge!({entry => nil})
    end
    @keywords.push(entry.keys.first).sort!
  end

(在上面的例子中,实际上没有任何成员变量@entries,@ keywords在调用add之后实际更新,但你知道它应该做什么。)如果上面的例子按预期工作,它似乎比第一次实现更有效。

Ruby有没有办法做这样的事情?感谢。

1 个答案:

答案 0 :(得分:3)

  

我通过调用' ='来使用公共setter方法。操作

不,你不是。那里没有setter调用。

  

如果上面的示例确实按预期工作,那么它似乎比第一个实现更有效。

假。这个例子正在做完全相同的事情(除了ivar赋值,这是一条指令),因此,性能将是相同的。始终衡量绩效,不要假设或猜测。

  def add(entry)
    if entry.instance_of?(Hash)
      @entries.merge!(entry)
    else
      @entries.merge!({entry => nil})
    end
    @keywords.push(entry.keys.first).sort!
  end
  

在上面的例子中,实际上在调用add之后,没有成员变量@entries,@ keywords实际更新

他们应该更新。必须是调用代码中的错误。顺便说一下,你应该这样写:

  def add(entry)
    if entry.instance_of?(Hash)
      entries.merge!(entry)
    else
      entries.merge!({entry => nil})
    end
    keywords.push(entry.keys.first).sort!
  end

您已定义了getter方法。很遗憾他们未被闲置。