4

Rubyには、接続の管理を容易にするクラスによって拡張されたDAOクラスがあります。これは、DB内のデータを表現および操作するクラスによって拡張され、さらに別のクラスによって拡張されます。動物の比喩を使用するには、次のようになります。

class Animal
 ...
end

class Mammal < Animal
 ...
end

class Feline < Mammal
 ...
end

class Cat < Feline
 ...
end

class Lion < Cat
 ...
end

...

PHPには__destruct、クラスを破棄/削除するときに実行されるメソッドがあります。そして、そのクラスが別のクラスを拡張する場合は、次のようparent::__destruct()にクラスの__destructメソッドに追加するだけです。

public function __destruct() {
  // Clean up code for this class here
  ...

  // Execute clean up code for Parent class
  parent::__destruct();
}

を除くすべてのクラスで同様のメソッドを使用できますAnimal。何も拡張されないため、このparent::__destruct();行は無効になります。

しかし、私が理解しているように、Rubyにはそのオブジェクトに対してこのようなメソッドがありません。cleanupファイナライザーは設定できますが、クラスを破棄/削除したいときはいつでも呼び出すことができるメソッドを入れることにしました。これで、クラスをに設定する前に行う必要のあるすべての処理が行われnilます。

しかし、これは新しい問題を引き起こします。メソッドに常に名前が付けられていて、を呼び出す場合は、cleanupを呼び出すlion_instance.cleanupと想定しますLion#cleanup。それではcleanup、クラス内で呼び出してから、チェーンの下流で呼び出すようにするにはどうすればよいですか?CatFeline

それとも、これは間違ったアプローチであり、あなたはより良いアイデアを持っていますか?

4

3 に答える 3

6

これに対する Ruby のイディオムは、動作するブロックに譲歩し、ブロックが戻ったときにクリーンアップを行うことです。Ruby のビルトイン "File.open" はこれを行います:

File.open("/tmp/foo") do |file|
  file.puts "foo"
end

ブロックが終了すると、何もしなくてもファイルが閉じられます。これは素晴らしいイディオムです。そのようなものを実装する方法は次のとおりです。

class Foo

  def self.open(*args)
     foo = new(*args)
     yield foo
     foo.close
  end

  def initialize
    # do setup here
  end

  def close
    # do teardown here
  end

end

そしてそれを使用するには:

Foo.open do |foo|
  # use foo
end

Foo#close後に自動的に発生しますend


これは、サブクラス化でも機能します。これは、クラス メソッドがインスタンス メソッドと同様に継承されるためです。スーパークラスは次のとおりです。

class Superclass

  def self.open(*args)
    o = new(*args)
    yield o
    o.close
  end

  def initialize
    # common setup behavior
  end

  def close
    # common cleanup behavior
  end

end

および 2 つの派生クラス:

class Foo < Superclass

  def initialize
    super
    # do subclass specific setup here
  end

  def close
    super
    # do subclass specific teardown here
  end

end

class Bar < Superclass

  def initialize
    super
    # do subclass specific setup here
  end

  def close
    super
    # do subclass specific teardown here
  end

end

使用する:

Foo.open do |foo|
  # use foo
end

Bar.open do |bar|
  # use bar
end

本当にクリーンアップが確実に行われるようにする必要がある場合は、クラス メソッドでensure句を使用します。

  def self.open(*args)
     foo = new(*args)
     begin
       yield foo
     ensure
       foo.close
     end
  end

このようにして、ブロックに例外があってもクリーンアップが行われます。

于 2012-09-21T19:49:20.090 に答える
3

ObjectSpace.define_finalizerを使用できます

何かのようなもの:

class Animal
  def initialize
    ObjectSpace.define_finalizer(self, proc { # your code })
   end
end
于 2012-09-21T19:35:59.387 に答える
1

メソッドが継承チェーンを上っていくというあなたの質問に誰も答えなかったので...

class Cat
  def rawr
    puts "rawr"
  end
end

class Kitty < Cat
  def rawr
    puts "meow"
    super
  end
end

Cat.new.rawr
"Rawr"

Kitty.new.rawr
"rawr"
"meow"

メソッド内では、super を呼び出すことで、同じ名前のスーパークラスのメソッドにアクセスできます。

于 2012-09-21T23:23:22.597 に答える