Ruby:实例方法的命名空间

时间:2013-02-12 13:44:31

标签: ruby namespaces instance-variables instance-methods

我有很多实例方法,都共享相同的实例变量。 由于课程变得庞大,我将方法分成大约50个模块。 然后剩下的课程包括所有这50个模块。

我最终得到了一个令人难以置信的丑陋代码,其中充满了像“module_name_method_name”这样的实例方法,以避免方法名称的冲突。 问题是每个模块可能具有相似(相似,不相同)的功能(反过来类似的方法名称)。

我目前的代码如下:

模块:

module Toyota
  def toyota_method1;@foo...;end
  def toyota_method2;@foo...;end
  ....
end

module Ford
  def ford_method1;@foo...;end
  def ford_method2;@foo...;end
  ....
end

....大约50个这样的模块

class Cars
  include Toyota
  include Ford
  include ...

  def foo
    @foo = "bar"
    @bar = "foo"
    ...

    toyota_method1
    ford_method2
    toyota_method2
    ...
  end
end

我怎样才能更好地设计代码? 最重要的是所有实例方法需要共享相同的实例变量..或者至少以某种方式可以访问相同的数据!

编辑: 我自己想出了这个:

class Toyota
  attr_accessor :foo

  def method1
    puts @foo
  end
end

class Ford
  attr_accessor :foo

  def method1
    puts @foo
  end
end

class Cars
  def foo
    @foo = "bar"

    toyota = Toyota.new
    toyota.foo = @foo
    toyota.method1

    ford = Ford.new
    ford.foo = @foo
    ford.method1
  end
end

cars = Cars.new
cars.foo

实际上它解决了丑陋的方法名称问题,但现在我正在处理新问题:变量@foo可能非常大并且它将自身重复50次(或更多)到内存中(因为我有50个这样的类)。

还有其他解决方案吗?

1 个答案:

答案 0 :(得分:1)

它不仅重复50次或更多,每个实例重复一次,因为它是一个实例变量。从我可以告诉你的代码,如果我错了你必须纠正我,你最好在类级别上使用inheritance和变量共享。如果你的汽车类真的需要知道它可能是所有类型的所有不同方法,那么这可能不起作用,但是我会说你从一开始就做了一些固有的错误。那么让我们来看看继承:

class Car
  attr_accessor :foo

  # lets you initialize attributes via a hash
  #
  def initialize attrs={}
    super()

    attrs.each do |att, value|
      self.send(:"#{att}=", value)
    end
  end

end

Toyota继承Car

class Toyota < Car

  def method1
    # do what you want to do in this method
  end

end

Ford相同:

class Ford < Car

  def method1
    # do what you want to do in this method
  end

end

像这样,您不必将名称空间放在方法前面:

Ford.new(:foo => 'fordfoo').foo #=> will put out «fordfoo»
Toyota.new(:foo => 'toyotafoo').foo #=> will put out «toyotafoo»


跨班级共享

现在,如果foo在所有汽车中共享,那么如果汽车类是静态的,您可以将其设为a)constant

class Car
  FOO = 'bar'

  def put_foo
    puts FOO
  end
end

像这样,CarToyotaFord的所有实例都可以访问静态常量FOO,它只会在内存中存在一次:

Toyota.new.put_foo #=> 'bar'

如果foo必须是可分配的,并且只需要存在一次整个继承树,请使用class variables

 class Car

   class << self
     def foo= data
       @@foo = data
     end
   end

   def foo= data
     self.class.foo = data
   end

   def foo
     @@foo
   end

 end

现在@@foo仅对继承树存在一次,所以如果你这样做:

 car    = Car.new
 toyota = Toyota.new

 toyota.foo = 'toyota'
 car.foo #=> 'toyota'

如果你没有注意,这可能会导致严重的问题,但如果foo对于所有课程都必须相同,那么这就是要走的路。 Thread Safety还有一些问题需要解决(Mutex}使用类变量。

如果CarToyotaFord都有不同的foo,但每个类的实例需要共享相同的foo(因此总共有3个foo) ),使用class instance variables

class Car
  class << self
    def foo= data
      @foo = data
    end

    def foo
      @foo
    end
  end

  def foo= data
    self.class.foo = data
  end

  def foo
    self.class.foo
  end
end

像这样你会得到:

car = Car.new
car.foo = 'bla'

toyota = Toyota.new
toyota.foo #=> is nil
toyota.foo = 'bar'

car.foo #=> still 'bla'
toyota.foo #=> is 'bar'

这些是跨实例共享相同数据的方法。