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

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次のいずれかにすることができます:

class Car
  FOO = 'bar'

  def put_foo
    puts FOO
  end
end

Carこのように、Toyotaまたはのすべてのインスタンスは、メモリ内に 1 回だけ存在する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継承ツリーは 1 回しか存在しないため、次のようにします。

 car    = Car.new
 toyota = Toyota.new

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

これは、注意を怠ると深刻な問題につながる可能性がfooありますが、とにかくすべてのクラスで同じでなければならない場合は、それが道です。また、スレッド セーフMutexには、クラス変数を使用して(で) 対処しなければならない問題がいくつかあります。

Carとすべてが異なるがToyota、各クラスのインスタンスが同じ foo を共有する必要がある場合 (したがって、合計で 3 つの foo になります)、クラス インスタンス変数を使用しますFordfoo

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 に答える