如何继承 class w\ ruby 中的属性

How to inherit class w\ properties in ruby

我是 Ruby 的新手,我来自 PHP,无法理解示例中的代码:

module Twitter
  class API < Grape::API
    version 'v1', using: :header, vendor: 'twitter'
    format :json
    prefix :api

Example from here

基本上我需要继承 class 如下:

class MyAPI < Twitter::API

但在那个 MyAPI class formatprefixversion 中不起作用,我不明白为什么,没有一本手册或教程不工作'不要回答我的问题。

例如format设置为api以json格式输出结果。在 Twitter::API class 中它运行良好,但在 child 中却不适用。所以我需要在每个 child classes 上写这个不好的地方。

versionformat 究竟是什么?它是变量(class 属性)还是 parent class 方法调用?

我假设它是一个调用并尝试 Twitter::API 像这样的东西:

def initialize
  format :json
end

但是报错:

TypeError: no implicit conversion of Symbol into String

def initialize
  self.format :json
end

NoMethodError: private method `format' called for #<MyAPI>

请尽可能详细。 您还可以指出解释它的文档吗?

format 类似于

class API
  private_class_method def self.format(kind)
    #...
  end
end

Ruby 中的私有方法不能用显式接收器调用(前面有一个点),只能调用隐式接收器(发送到 self 的当前值)。在 class 定义中,self 是被定义的 class。这就是为什么你可以写

def self.format(...)

而不是

def API.format(...)

因此,在您的代码中,

class MyAPI < API
  format :json
  # ...
 end

它正在 class 对象 MyAPI 上调用方法 format,由于继承自 API 作为 class 正在定义 。查看 Grape 源代码,format 将(最终)在实例变量中设置一个值。让我们将其简化为 @format(实际上并非如此,它是继承的而不是在 API 上,但是...简化示例)。我们再做一个方法,看看实例变量的值是多少。

class API
  private_class_method def self.format(what)
    @format = what
  end

  def self.peek_format
    @format
  end
end

现在让我们做一个子class:

class SubAPI < API
end

现在,要设置格式,我们想使用类似 API.format(:json) 的东西,但我们不能,因为它是私有的。所以我们将创建一个上下文,其中 format(:json) 自然地转到 API:

class API
  format :json
end
API.peek_format
# => :json

格式已设置。一切似乎都很好。现在让我们看看 subclass:

会发生什么
class SubAPI
  format :txt
end
SubAPI.peek_format
# => :txt

但是,

API.peek_format
# => :json

方法是继承的;实例变量不是。每个 class 实例(即类型 Class 的对象)都有自己的一组实例变量,就像每个其他对象都有自己的一组实例变量一样,不与相同 [=63 的其他对象共享=].

如果你真的希望每个子class做同样的初始化,你可以这样做(虽然这不是最好的主意):

class API
  private_class_method def self.format(what)
    @format = what
  end

  def self.peek_format
    @format
  end

  # common initialisation
  private_class_method def self.initialize_class
    format :json
  end

  # whenever we get a new subclass, run the initialisation
  private_class_method def self.inherited(subclass)
    subclass.instance_eval do
      initialize_class
    end
  end

  # now initialise this class too
  initialize_class
end

class SubAPI < API
end

API.peek_format
# => :json
SubAPI.peek_format
# => :json

但我劝你不要这样做。如果您正在使用 MyAPI,那么您可能没有使用 API 本身;您不需要在其中设置格式(或其他参数)。