0

我有很多实例方法,它们都共享相同的实例变量。由于这个类变得很大,我将这些方法分成大约 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 个这样的类)。

还有其他解决方案吗?

4

1 回答 1

1

它不仅重复 50 次或更多,而且每个实例都重复,因为它是一个实例变量。根据我对您的代码的了解,如果我错了,您必须纠正我,您最好在类级别使用继承和变量共享。如果您的汽车课程确实需要了解所有可能是所有类型的模型的所有不同方法,这可能行不通,但是我会说您从一开始就做错了。那么让我们看一下继承:

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

继承ToyotaCar

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) 汽车类的常量(如果它是静态的):

class Car
  FOO = 'bar'

  def put_foo
    puts FOO
  end
end

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

Toyota.new.put_foo #=> 'bar'

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

 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所有课程都必须相同,那么这是要走的路。线程安全也存在​​一些问题,您必须Mutex使用类变量来解决(使用 )。

如果Car, Toyotaand Fordall 有不同foo的 , 但是每个类的实例需要共享同一个 foo (所以总共是 3 个 foo), 使用类实例变量:

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'

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

于 2013-02-12T15:50:03.593 回答