【问题标题】:Can I make a class that presents methods and variables transparently?我可以创建一个透明地呈现方法和变量的类吗?
【发布时间】:2014-02-18 20:14:11
【问题描述】:

我想用 Ruby 做一些配置文件工作。配置的某些元素名义上依赖于其他元素,但不一定。

例如,在使用配置时,我想这样做:

require_relative "config" 
require_relative "overrides" 
dosomething_with(Config.libpath)

在“配置”中,我想要类似的东西:

require 'ostruct'
Config = OpenStruct.new
Config.basepath = "/usr"
Config.libpath = lambda {Config.basepath + "/lib"}    # this is not quite what I want

在“覆盖”中,用户可能会覆盖Config.basepath,我希望 Config.libpath 采用自然值。但用户可能Config.libpath 覆盖为某个常量。

我希望能够只说 Config.libpath 并获取计算值(如果尚未被覆盖)或定义值(如果已被覆盖)。

这是我会用 Ruby 做的事情吗?这似乎是我所看到的 OpenStruct 工作方式的自然延伸。

【问题讨论】:

  • OpenStruct 使用 method_missing 来发挥它的魔力,如果你对性能没有问题,不妨看看它
  • 小心使用 OpenStruct,因为它会很快消耗内存。我自己也经历过,但是See this Question

标签: ruby lazy-loading


【解决方案1】:

这个呢:

require 'ostruct'

Config = OpenStruct.new
Config.basepath = "/usr"

def Config.libpath
  # Suggested by Nathaniel himself
  @table[:libpath] || basepath + "/lib"

  # The next alternatives require def Config.libpath=(libpath) ...
  # instance_variable_defined?(:@libpath) ? @libpath : basepath + "/lib"
  # or 
  # @libpath || basepath + "/lib" , depending on your needings
end

# Needed only if @table[:libpath] is not used
# def Config.libpath=(libpath)
#   @libpath = libpath
# end

# Default basepath, default libpath
p Config.libpath #=> "/usr/lib"

# custom basepath, default libpath
Config.basepath = "/var"
p Config.libpath #=> "/var/lib"

# Custom libpath
Config.libpath = '/lib'
p Config.libpath #=> "/lib"

【讨论】:

  • 正是我想要的!看了下OpenStruct的源码,用@table[:libpath]代替@libpath好像也行,然后就不用定义libpath=方法了。
  • 哦,是的,我过去也看过一次,你提醒我它使用@table,我更新了答案 =)
猜你喜欢
  • 2017-11-12
  • 1970-01-01
  • 2014-06-17
  • 2020-10-21
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 2019-10-12
  • 2019-05-05
相关资源
最近更新 更多