如何在ruby中继承类w \属性

时间:2016-02-04 02:18:59

标签: ruby grape

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

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

Example from here

基本上我需要继承该类,如下所示:

class MyAPI < Twitter::API

但是在那个MyAPI课程formatprefixversion没有工作,我无法理解为什么,也没有任何手册或教程没有。回答我的问题。

例如format正在设置api以json格式输出结果。在Twitter :: API类中,它运行良好,但在子类中,它并不适用。因此,我需要在每个儿童班上写下这不是好事。

versionformat实际上是什么?它是变量(类属性)还是它的父类方法调用?

我假设它是一个电话,并在Twitter :: API中尝试类似:

def initialize
  format :json
end

但是得到一个错误:

  

TypeError:没有将Symbol隐式转换为String

def initialize
  self.format :json
end
  

NoMethodError:私有方法`格式&#39;呼叫#&lt; MyAPI&gt;

请尽可能详细。 你能指点我解释它的文件吗?

1 个答案:

答案 0 :(得分:2)

format就像是

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

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

的原因
def self.format(...)

而不是

def API.format(...)

因此,在您的代码中,

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

它正在类对象format上调用方法MyAPI,因为正在定义类,因为API的继承。查看Grape源,format将(最终)在实例变量中设置一个值。我们将它简化为@format(它实际上不是那个,它是继承的而不是API,但是......简化了示例)。我们还要制作另一种方法,看看实例变量的值是什么。

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

  def self.peek_format
    @format
  end
end

现在让我们创建一个子类:

class SubAPI < API
end

现在,要设置格式,我们希望使用类似API.format(:json)的内容,但我们不能,因为它是私有的。因此,我们将创建format(:json)自然转到API的上下文:

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

格式已设置。一切似乎都很好。现在让我们看看子类会发生什么:

class SubAPI
  format :txt
end
SubAPI.peek_format
# => :txt

但是,

API.peek_format
# => :json

方法是遗传的;实例变量不是。每个类实例(即类型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本身;您不需要在其中设置格式(或其他参数)。