如何控制方法范围?

时间:2014-06-06 07:39:55

标签: ruby

我将我的问题抽象为以下情况。

# /somewhere/build_ability/car.rb
module BuildAbility
  module Car
    def build_car
      build_component
    end

    def build_component
      # Specific designed for build car, not common used
      # Totally different from build_component in BuildAbility::Ship
    end
  end
end

# /somewhere/build_ability/ship.rb
module BuildAbility
  module Ship
    def build_ship
      build_component
    end

    def build_component
      # Specific designed for build ship, not common used
      # Totally different from build_component in BuildAbility::Car
    end
  end
end

# /somewhere/omni_factory.rb
class OmniFactory
  include BuildAbility::Car
  include BuildAbility::Ship

  def build_component
    # common used method
  end
end

BuildAbility::Car添加到OmniFactory的目的是介绍build_car,而不想介绍build_component

build_component中的BuildAbility::Car是专为build_car设计的,它仅适用于build_car,在其他地方无用。因此,当OmniFactory包含BuildAbility::Car时,无需引入build_component

BuildAbility::Ship中的相同情况。

那么我应该将build_component放在car.rb中以达到目的?

我认为这可能发生在宝石中,宝石可能不希望某些低级基本功能暴露给用户,并且只在gem文件中使用。

以下代码是解决方案之一,就像关闭一样,但我认为这种方式太难看了,还有其他一些解决方案吗?

# /somewhere/build_ability/car.rb
module BuildAbility
  module Car
    build_component = lambda {
      # Specific designed for build car, not common used
      # Totally different from build_component in BuildAbility::Ship
    }

    define_method :build_car do
      build_component.call
    end
  end
end

# /somewhere/build_ability/ship.rb
module BuildAbility
  module Ship
    build_component = lambda {
      # Specific designed for build ship, not common used
      # Totally different from build_component in BuildAbility::Car
    }

    define_method :build_ship do
      build_component.call
    end
  end
end

# /somewhere/omni_factory.rb
class OmniFactory
  include BuildAbility::Car
  include BuildAbility::Ship

  def build_component
    # common used method
  end
end

1 个答案:

答案 0 :(得分:3)

您可以将build_component作为模块方法,当您include模块时,不会继承该模块。

这是一个有效的例子:

# /somewhere/build_ability/car.rb
module BuildAbility
  module Car
    def build_car
      Car.build_component
    end
    def self.build_component
      p "car"
    end
  end
end

# /somewhere/build_ability/ship.rb
module BuildAbility
  module Ship
    def build_ship
      Ship.build_component
    end
    def self.build_component
      p "ship"
    end
  end
end

# /somewhere/omni_factory.rb
class OmniFactory
  include BuildAbility::Car
  include BuildAbility::Ship

  def build_component
    p "omnifactory"
    # common used method
  end
end

OmniFactory.new.build_component
OmniFactory.new.build_car
OmniFactory.new.build_ship

输出:

"omnifactory"
"car"
"ship"

通过这种方式,OmniFactory build_component方法不会干扰任何事情。此外,self.build_component中的BuildAbility::Car方法不会包含在OmniFactory中。

另一种方法(有点脏),让build_component成为一个类的成员。

# /somewhere/build_ability/car.rb
module BuildAbility
  module Car
    def build_car
      CarStrategy.build_component
    end

    class CarStrategy
      def self.build_component
        p "car"
      end
    end
  end
end

但是,对我来说,这个解决方案看起来并不像模块方法那么简单明了。