Rubyの「require」ステートメントはクラス定義の内部または外部にありますか?

StackOverflow https://stackoverflow.com/questions/605261

  •  03-07-2019
  •  | 
  •  

質問

Rubyでクラスファイルを使用する場合、「requires」ステートメントをファイルの上部に配置しますか、それともクラス定義内に配置しますか?

役に立ちましたか?

解決

技術的には、実際には問題ではありません。 require は通常のメソッド呼び出しであり、呼び出される範囲はその動作に影響しません。配置の唯一の違いは、配置されたコードが評価されたときに実行されることです。

実際には、ファイルの依存関係がひと目でわかるように、最上位に配置する必要があります。それが伝統的な場所です。

他のヒント

上部。

require 'rubygems'
require 'fastercsv'

class MyClass
  # Do stuff with FasterCSV
end

ファイルの先頭に require を配置しない理由として考えられるのは、読み込みに時間がかかり、常に実行されるわけではないことです。私の場合、たとえばコードとそのテストが同じファイルに含まれている場合があります。これは、特に小さなライブラリコードの場合に時々行いたいことです。その後、エディターからファイルを実行し、テストを実行できます。この場合、ファイルが他の場所から require dされたとき、 test / unit をロードしたくありません。

次のようなもの:

def some_useful_library_function()
  return 1
end

if __FILE__ == <*>
  require 'test/unit'
  class TestUsefulThing < Test::Unit::TestCase
    def test_it_returns_1
      assert_equal 1, some_useful_library_function()
    end
  end
end

実際に配置する場所は重要ではありませんが、 class または module 式の内部に配置すると、あなたが require dファイルにあるものをクラスの名前空間にインポートするように、それは真実ではありません:すべてがグローバルな名前空間(またはライブラリで >)。

そのため、混乱を避けるために、それらを一番上に置いてください。

ファイルの先頭では、大部分の(すべてではない)言語がこの方法でインポートを処理します。この方法で処理する方がずっときれいで簡単だと思います。

この方法は本当に理にかなっていると思います...ファイルの途中で取得するように:

class Foo
  def initialize(init_value)
    @instance_var = init_value

# some 500 lines of code later....

  end
end

class Bar
# oh look i need an import now!
require 'breakpoint'

ご覧のとおり、それらを追跡するのは非常に困難です。インポートされた関数をコードの以前で使用したい場合は言うまでもありませんが、他のインポートはそのクラスに固有であるため、バックトラックして再度含める必要があります。同じファイルをインポートすると、実行時にも多くのオーバーヘッドが発生します。

require ステートメントはクラス内に属していると思います。クラスを使用するということは、OOPの基本原則を受け入れることを意味します。つまり、オブジェクトはできるだけ疎結合でなければなりません。それは外部の依存関係を最小限に抑えることを意味します。後でクラスを独自のファイルに移動する場合、クラスが消費するすべての必要な require ステートメントを追跡しなかったため、クラスを中断させたくありません。

ファイル内で重複する require ステートメントが発生しても問題は発生せず、コードを継承する次のプログラマーによって必然的に発生するリファクタリングが簡素化されます。

ほとんどの回答では、ファイルの先頭に require ステートメントを置くことをお勧めします。ただし、ネストされたクラス/モジュールが必要な場合は、代わりにクラスの最上部に配置することを検討してください。この例を見てください:

# foo.rb
require './foo/bar'

class Foo < Struct.new(:name, :description)
  def bar
    Bar.new(self)
  end
end

# foo/bar.rb
class Foo
  class Bar < Struct.new(:foo)
  end
end

irb:

require './foo'
# ...
# TypeError (superclass mismatch for class Foo)

これは、 Bar Foo 内にネストされており、 Bar クラスを内にネストして、 Foo クラス。ただし、 Foo はまだ定義されていないため、ネスト構造で定義されています。 Bar が正常に必要になったら、別のクラスを継承する Foo クラスを定義しようとします。これは Foo が既に(ネストされた構造によって)定義されており、継承はクラスの初期定義でのみ発生するため、失敗します。したがって、レイズ:

  

TypeError(クラスFooのスーパークラスの不一致)

この問題は、requireステートメントを Foo クラス内に移動するだけで解決できます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top