我可以使用超类方法为ruby中的子类设置类变量吗?

时间:2018-01-21 18:42:32

标签: ruby inheritance protocols class-variables

好的,所以我试图在ruby中设置我自己的子类化结构,以允许与Swift中的协议模式匹配的功能。我目前的方法是创建两个基类,一个叫做Protocol,它允许用x个必需方法声明协议,另一个叫做SwiftClass,它允许子类“继承”协议。

协议类

class Protocol
  @@required_methods = []

  def self.required_method(method_name)
    @@required_methods << method_name
  end

  def self.required_methods
    return @@required_methods
  end
end

Swift Class

class SwiftClass
  @@protocols = []

  def self.inherit_protocol(protocol_name)
     protocol = Object.const_get(protocol_name)
     @@protocols << protocol
  end

  def self.inherit_protocols(*protocol_names)
    protocol_names.each do |protocol_name|
      inherit_protocol(protocol_name)
    end
  end

  def self.verify_conforms_to_protocols
    @@protocols.each do |protocol|
      if protocol.superclass != Protocol
        raise "ERROR: #{protocol} must be a subclass of Protocol"
      end
      if (missing_methods = self.missing_methods_for protocol).length > 0
        raise "\nERROR: #{self} does not conform to protocol #{protocol}. \nMISSING METHODS: #{missing_methods.join(", ")}"
      end
    end
  end

  def self.missing_methods_for(protocol)
    protocol.required_methods.select do |required_method|
      !self.method_defined? required_method
    end
  end

end

然后,我可以创建一个具有所需方法的协议

class SampleProtocol < Protocol
  required_method :number_of_sections_in
  required_method :number_of_rows_in_section
end

并设置一个类来继承此协议

class SampleClass < SwiftClass
  inherit_protocols :SampleProtocol
  verify_conforms_to_protocols
end

到目前为止,一切都按照应有的方式运作。如果我运行代码,它会引发我在SwiftClass中设置的错误

ERROR: SampleClass does not conform to protocol SampleProtocol. 
MISSING METHODS: number_of_sections_in, number_of_rows_in_section

然后,如果我将方法添加到SampleClass并运行它,它不再引发任何错误:

class SampleClass < SwiftClass
  inherit_protocols :SampleProtocol

  def number_of_sections_in; end
  def number_of_rows_in_section; end

  verify_conforms_to_protocols
end

大多数对ruby一无所知的人可能已经看到了这段代码的明显问题;类变量@@ required_methods和@@ protocols都是在超类级别定义的,因此每次我在子类中添加它时,它都会扩展到每个其他子类。例如,如果我在SampleClass声明之前添加一个单独的协议

class SomeOtherProtocol < Protocol
   required_method :cell_for_row_at
end

然后运行代码我得到错误

ERROR: SampleClass does not conform to protocol SampleProtocol. 
MISSING METHODS: cell_for_row_at

因为@@ required_methods从每个Protocol子类收集所有必需的方法。对于SwiftClass的每个子类,@@ protocols也是如此。

所以我的问题是,我可以使用超类为每个子类设置类变量吗?我希望@@ required_methods变量为Protocol的每个子类保存不同的值,并且@@ protocols变量为SwiftClass的每个子类保存不同的值,但是我仍然希望在超类中保持这个逻辑,这样我就不会必须在每个子类中重复它。

如果可能的话,我想在SwiftClass中保留完全相同的继承协议的结构,这样我就可以设置继承协议的所有“inherit_protocols:SomeProtocol”。使用“method:some_method”调用将方法添加到新协议也是一样。

0 个答案:

没有答案