Ruby 从模块内部调用外部类实例的方法
我希望创造一个宝石,可以称为如下Ruby 从模块内部调用外部类实例的方法,ruby,scope,rubygems,Ruby,Scope,Rubygems,我希望创造一个宝石,可以称为如下 # initialization location = DarkSky::Location.new [45, -90] # calling certain methods location.current.temperature location.tomorrow.temperature_high # not shown below 目前,我的代码的结构是这样的(本文中有许多方法) location.rb module DarkSky # other m
# initialization
location = DarkSky::Location.new [45, -90]
# calling certain methods
location.current.temperature
location.tomorrow.temperature_high # not shown below
目前,我的代码的结构是这样的(本文中有许多方法)
location.rb
module DarkSky
# other methods are here, as this is for a Gem
class Location
def initialize(location)
@location = location
end
def full_data
# return common data between `Current` and `Tomorrow` classes
{
currently: {
temperature: 42
}
}
end
end
end
module DarkSky
class Location
module Current
def self.temperature
full_data[:currently][:temperature] # this line
end
end
# alias name for client simplicity
def current
Current
end
end
end
module DarkSky
# other methods are here, as this is for a Gem
class Location
attr_reader :current
def initialize(location)
@location = location
@current = Current.new self # here's the "hidden" initialization with the instance as a parameter
end
def full_data
# return common data between `Current` and `Tomorrow` classes
{
currently: {
temperature: 42
}
}
end
end
end
module DarkSky
class Location
class Current
def initialize(location)
# keep a reference to the location (for the shared data)
@location = location
end
def apparent_temperature
@location.full_data[:currently][:temperature]
end
end
end
end
current.rb
module DarkSky
# other methods are here, as this is for a Gem
class Location
def initialize(location)
@location = location
end
def full_data
# return common data between `Current` and `Tomorrow` classes
{
currently: {
temperature: 42
}
}
end
end
end
module DarkSky
class Location
module Current
def self.temperature
full_data[:currently][:temperature] # this line
end
end
# alias name for client simplicity
def current
Current
end
end
end
module DarkSky
# other methods are here, as this is for a Gem
class Location
attr_reader :current
def initialize(location)
@location = location
@current = Current.new self # here's the "hidden" initialization with the instance as a parameter
end
def full_data
# return common data between `Current` and `Tomorrow` classes
{
currently: {
temperature: 42
}
}
end
end
end
module DarkSky
class Location
class Current
def initialize(location)
# keep a reference to the location (for the shared data)
@location = location
end
def apparent_temperature
@location.full_data[:currently][:temperature]
end
end
end
end
在第二个块中,我希望从第一个块调用full_data
。我遇到的问题是,full\u data
是一个实例方法,而我只能从位置
范围内访问它(而不是内部当前
范围)
我已经搜索了很多,但是没有找到类似的方法,其中的方法是实例方法,而不是类方法
旁注-无论
Current
是类还是模块。无论哪种方法,我都能很好地找到解决方案。请记住,除了参数列表中的参数外,每个方法调用都有一个额外的参数,即方法的接收者。如果没有明确写入接收器,self
被假定为接收器
关于数据共享,模块DarkSky::Location::Current和类DarkSky::Location之间没有关系。您对full_data
的方法调用没有指定显式接收器,因此它假定self
为接收器。在您的情况下,self
等于DarkSyk::Location::Current
,并且此模块中没有方法完整的\u数据
让我们假设您的方法完整的\u数据
确实需要访问其DarkSky::Location对象;在您发布的代码中,情况并非如此,但我想您已经精简了代码,以便更容易理解您的问题。在这种情况下,还必须提供这样的位置对象;除此之外,full_data
还应该如何计算结果
当然,如果full_data
确实不需要Location
中的任何实例变量,那么它应该是Location的类方法,而不是实例方法
在您的例子中,我猜Location对象存储某个位置的(天气)数据,而您的温度方法返回温度。但它应该返回哪个位置的温度?东京还是维也纳?如果不知道地点,知道温度是没有意义的。使其工作的一种方法是添加位置作为参数:
module Current
# where : Object of class DarkSky::Location
def self.temperature(where)
where.full_data[:currently][:temperature] # this line
end
end
这只是一个例子。我不知道它是否适合您的应用程序。鉴于在这种情况下,Current
或类似的实例将只有一个,这可以通过在Location
初始化时创建一个类实例,并使用attr\u reader
访问它来实现
这是基于原始帖子的工作代码
location.rb
module DarkSky
# other methods are here, as this is for a Gem
class Location
def initialize(location)
@location = location
end
def full_data
# return common data between `Current` and `Tomorrow` classes
{
currently: {
temperature: 42
}
}
end
end
end
module DarkSky
class Location
module Current
def self.temperature
full_data[:currently][:temperature] # this line
end
end
# alias name for client simplicity
def current
Current
end
end
end
module DarkSky
# other methods are here, as this is for a Gem
class Location
attr_reader :current
def initialize(location)
@location = location
@current = Current.new self # here's the "hidden" initialization with the instance as a parameter
end
def full_data
# return common data between `Current` and `Tomorrow` classes
{
currently: {
temperature: 42
}
}
end
end
end
module DarkSky
class Location
class Current
def initialize(location)
# keep a reference to the location (for the shared data)
@location = location
end
def apparent_temperature
@location.full_data[:currently][:temperature]
end
end
end
end
current.rb
module DarkSky
# other methods are here, as this is for a Gem
class Location
def initialize(location)
@location = location
end
def full_data
# return common data between `Current` and `Tomorrow` classes
{
currently: {
temperature: 42
}
}
end
end
end
module DarkSky
class Location
module Current
def self.temperature
full_data[:currently][:temperature] # this line
end
end
# alias name for client simplicity
def current
Current
end
end
end
module DarkSky
# other methods are here, as this is for a Gem
class Location
attr_reader :current
def initialize(location)
@location = location
@current = Current.new self # here's the "hidden" initialization with the instance as a parameter
end
def full_data
# return common data between `Current` and `Tomorrow` classes
{
currently: {
temperature: 42
}
}
end
end
end
module DarkSky
class Location
class Current
def initialize(location)
# keep a reference to the location (for the shared data)
@location = location
end
def apparent_temperature
@location.full_data[:currently][:temperature]
end
end
end
end
这允许出现一个名称空间,但实际上只是类实例的一个getter,然后让您获得各个方法。类方法temperature
必须创建Location
的实例才能调用full\u data
。我怀疑那是你的意图。为什么要将full_data
作为实例方法?@CarySwoveland每个位置都有自己的数据。我之所以使用Current
,完全是出于名称空间的目的。我的想法是,它必须创建一个实例,而这个实例不允许我在文章的开头实现所需的行为。缓存位置
数据以避免许多请求,这就是为什么实例化多个类不是解决问题的正确方法。“从模块内部调用外部类实例的方法”——Ruby中没有“外部类”这样的东西。Ruby没有像Beta或Newspeak那样的嵌套类。为什么这是一个模块呢。由于完整的_数据是一项要求,因此绑定将非常紧密。为什么不让这些实例方法成为Location
?@engineersmnky的目的是匹配第一个代码块中的API。我完全可以用current\u temperature
作为一种方法,但我不喜欢这样称呼它(“current”应该是一个名称空间,因为它的数据是独立的)。读者是成年人,不需要用粗体字来理解他们在读什么。此外,这里使用的“真的”是一个无足轻重的词。也许我还没有这样的智力水平,但至少对我来说,如果用某种方式强调单词,如果人们应该特别注意它们,它会有所帮助。也谢谢你指出,“真的”在这里是不合适的;由于不是以英语为母语的人,我犯了一个错误,从我的语言中把它翻译得有点太字面了。如果我理解正确,我可以省略这个词,而不改变整个句子的意思。在日常会话中,人们可能会说“X真的需要Y”,以表明如果X没有得到Y,它将有一个大问题(不仅仅是一个问题:-)。在这里,如果需要对编码问题做出准确的回答,X要么“需要”是的,不是的。至于用粗体字,这不仅是没有必要的,而且表明读者可能不理解你写的没有重点的内容,而有些读者可能不会欣赏。例如,在笔记中突出显示单词是可以的,但前提是它们是你的笔记。