从内部模块调用外部类实例的方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从内部模块调用外部类实例的方法相关的知识,希望对你有一定的参考价值。

我正在寻找一个可以如下调用的Gem

# 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

current.rb

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

在第二个区块中,我打算从第一个区块调用full_data。我遇到的问题是full_data是一个实例方法,而我只能从Location范围内访问它(不是内部Current范围)

我搜索了很多,但是找不到类似的东西,其中方法是实例方法,而不是类方法。

旁注 - Current是一个类或模块并不重要。无论哪种方式,我都很擅长解决方案。

答案

鉴于在这种情况下,只会有一个Current或类似的实例,这可以通过在Location初始化时创建一个类实例,并使用attr_reader来访问它来实现。

这是基于原始帖子的工作代码。

location.rb

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

current.rb

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,然后让你获得各个方法。

另一答案

请记住,除了参数列表中的参数列表之外,每个方法调用都有一个附加参数,该参数是方法的接收者。如果没有明确写入接收器,则self被假定为接收器。

关于数据共享,模块DarkSky :: Location :: Current和类DarkSky :: Location之间没有任何关系。您对full_data的方法调用没有指定显式接收器,因此它假设self作为接收器。在你的情况下,self等于DarkSyk::Location::Current,并且在这个模块中没有方法full_data

让我们假设你的方法full_data确实需要访问它的DarkSky :: Location对象;在您发布的代码中,情况并非如此,但我想您已经删除了代码,以便更容易理解您的问题。在这种情况下,您还必须提供这样的Location对象; full_data应该怎么知道如何计算结果?

当然,如果full_data确实不需要来自Location的任何实例变量,它应该是Location的类方法,而不是实例方法。

在你的情况下,我猜一个Location对象存储某个位置的(weather-)数据,你的temperature方法返回温度。但是它应该返回温度的哪个位置?东京还是维也纳?不知道这个地方,知道温度是没有意义的。使其工作的一种方法是将地点添加为参数:

module Current
  # where  : Object of class DarkSky::Location
  def self.temperature(where)
    where.full_data[:currently][:temperature] # this line
  end
end

这只是一个例子。不知道它是否适合您的应用,我不知道。

以上是关于从内部模块调用外部类实例的方法的主要内容,如果未能解决你的问题,请参考以下文章

内部类之局部内部类

JavaSE学习 外部调用内部类的方法

在静态方法中new 一个内部类对象和new 一个外部类对象的区别

java内部类的静态嵌套类

静态方法中不可直接new内部类实例对象问题

内部类专题(自学)