Есть ли преимущество использования косвенности при включении модуля (из 7 языков за 7 недель, Ruby день 3) - PullRequest
4 голосов
/ 11 декабря 2011

Брюс приводит следующий пример в «Семи языках за семь недель», Ruby day 3, стр. 38:

module ActsAsCsv
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def acts_as_csv
      include InstanceMethods
    end
  end

  module InstanceMethods
    def read
       #fill @csv_contents and @headers from file self.class.to_s.downcase + '.txt'
    end

    attr_accessor :headers, :csv_contents

    def initialize
      read
    end
  end
end

class RubyCsv
  include ActsAsCsv
  acts_as_csv
end

m = RubyCsv.new
puts m.headers.inspect
puts m.csv_contents.inspect

Я не вижу никакой причины для косвенного обращения, используемого def self.included(base) и ClassMethods.Есть ли преимущество вышеприведенного кода перед простым включением модуля InstanceMethods?


Подробно: Под «простым включением модуля InstanceMethods» я подразумеваю следующий код:

  module InstanceMethods #defined as above
    def read
       #fill @csv_contents and @headers from file self.class.to_s.downcase + '.txt'
    end

    attr_accessor :headers, :csv_contents

    def initialize
      read
    end    
  end

class RubyCsv
  include InstanceMethods
end

m = RubyCsv.new
puts m.headers.inspect
puts m.csv_contents.inspect

Из-за утки, разве это не так хорошо, как проходить через base.extend ClassMethods?

Ответы [ 2 ]

4 голосов
/ 11 декабря 2011

Исходный код позволяет вам сделать это:

class A
  include ActsAsCsv
end

class B < A
  acts_as_csv
end

Хотя использование наследования - это больше дело вкуса, в этом случае было бы чище, если бы

  • больше методов, чемпросто acts_as_csv будет добавлено аналогично A
  • ActsAsCsv ожидается, будет включен классом, от которого наследуются многие классы (как, например, BaseModel)

Дальнейшее преимущество возникает, когда

  • метод acts_as_csv более сложный, чем просто включение InstanceMethods
  • acts_as_csv с аргументом, например acts_as_csv :separator => " "
3 голосов
/ 11 декабря 2011

Одним из преимуществ является передача цели между кодом (и исходным автором) и теми, кто рассуждает о коде позже.(И механизм разрешения параметров.)

acts_as_csv утверждает аспект поведения RubyCsv.

include ActsAsCsv менее декларативен.Предоставляет ли он дополнительные методы, фундаментально ли он изменяет функциональность базового класса, или оба, или ...?Вы не узнаете, пока не прочитаете документы.Вы можете не знать, пока не прочитаете документы для acts_as_csv, но это более коммуникативно.

В этом разница между «это то, что я есть» и «это то, что я могу делать».Не увлекайтесь конкретным примером - рассмотрите механизм того, что делается, и как.

Этот механизм - одна из причин, по которой код Ruby может выглядеть как проблема, которую он пытается решить, а не просто Ruby.Это один из способов реализации микро-DSL, которые помогают сделать Ruby таким же выразительным, как и он.

...