4

オーバーライドされないメソッドを持つ基本クラス A があります。

class A
  def dont_override_me
    puts 'class A saying, "Thank you for not overriding me!"'
  end
end

そして、A を拡張してdont_override_meメソッドをオーバーライドしようとする別のクラス B。

class B < A
  def dont_override_me
    puts 'class B saying, "This is my implementation!"'        
  end
end

B をインスタンス化して を呼び出すとdont_override_me、クラス B のインスタンス メソッドが呼び出されます。

b = B.new
b.dont_override_me # => class B saying, "This is my implementation!"

これはルビーの性質によるものです。理解できる。

ただし、基本クラスのメソッドdont_override_meを派生クラスでオーバーライドできないようにするにはどうすればよいですか? finalRuby の Java のようなキーワードは見つかりませんでした。C++ では、基本クラスのメソッドを非仮想にすることができるため、派生クラスによってオーバーライドできなくなります。ルビーでこれを達成するにはどうすればよいですか?

4

4 に答える 4

6

変更イベントをフックして元に戻すことでそれを行うことができますが、私には少し臭いようです:

http://scie.nti.st/2008/9/17/make-methods-immutable-in-ruby

それはRubyを定義するものの1つなので、それと戦うことは少し無意味に思えます. 誰かが何かを再定義してひどく壊れたら..それは彼らの問題です;-)

于 2009-04-02T07:28:40.870 に答える
4

これを行う方法は次のとおりです 。 http://www.thesorensens.org/2006/10/06/final-methods-in-ruby-prevent-method-override/

これは、「ファイナライザー」(gem install finalizer) と呼ばれる gem にもパッケージ化されています。

これは、method_added コールバックを利用して、新しいメソッド名を作成したいメソッドのリストと比較しますfinal

于 2009-04-02T07:29:08.297 に答える
1

私はお勧め:

class A #This is just as you've already defined it.
  def dont_override_me
    puts 'class A saying, "Thank you for not overriding me!"'
  end
end

module BehaviorForB
  def dont_override_me
    puts 'class B saying, "This is my implementation!"'        
  end

  def greet
    "Hello, Friend."
  end
end

class B < A
  include BehaviorForB
end

b = B.new
b.dont_override_me #=> class A saying, "Thank you for not overriding me!"
b.greet #=> Hello, Friend.

B のメソッドを mixin に隠しておくことで、まさにあなたが望むものを手に入れることができます。A にまだない B のメソッドのすべてのメソッドが使用可能になります。すでに A にあるメソッドはオーバーライドされません。

于 2010-08-09T18:47:36.817 に答える
0

メソッドがサブクラスによってオーバーライドされるのを防ぐ 1 つの方法 (ただし、お勧めしません):

class Class
  def frozen_method(method)
    if class_variable_defined?(:@@__frozen_methods__)
      add= class_variable_get(:@@__frozen_methods__) | [method]
      class_variable_set(:@@__frozen_methods__,add)
    else
      class_variable_set(:@@__frozen_methods__,[method])
    end
    class << self
      def inherited(child)
        def method_added(method)
          if class_variable_get(:@@__frozen_methods__).include? method
            send(:remove_method, method)
            error="Cannot change method #{method} because it's not overridde"
            raise TypeError, error
          end
        end
      end
    end
  end
end

class Foo
  def hello
    'hello'
  end
  def foo
    'foo'
  end

  frozen_method :foo
end

class Bar < Foo
  def foo
    'new foo'
  end
end

#=> TypeError: Cannot change method foo because it's not overridde

Bar.new.foo  #=> 'foo'

警告: この例は完全ではありません。サブクラスで以前に定義されたメソッドを追加する場合frozen_method、このメソッドがサブクラスで変更されると、その実装が失われます。

于 2016-10-25T19:02:18.557 に答える