Ruby:实例方法的名称间距



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

还有其他解决方案吗?

它不仅重复了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

Car:继承Toyota

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在所有汽车中共享,那么如果它是静态的,您可以使它成为汽车类上的一个常数:

class Car
  FOO = 'bar'
  def put_foo
    puts FOO
  end
end

像这样,CarToyotaFord的所有实例都可以访问静态常量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)。

如果CarToyotaFord都有不同的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'

这些是在实例之间共享相同数据的方法。

相关内容

  • 没有找到相关文章

最新更新