代码之家  ›  专栏  ›  技术社区  ›  Chirantan

如何使基类方法在ruby中不可重写?

  •  2
  • Chirantan  · 技术社区  · 16 年前

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

    以及另一个扩展A并试图重写 dont_override_me 方法。

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

    如果我实例化B并调用 ,将调用类B的实例方法。

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

    这是因为ruby的特性。可以理解。

    不要凌驾于我之上 final 在java for ruby中。在C++中,基类方法可以非虚拟化,以便它们由派生类变得不可重写。我如何在ruby中实现这一点?

    4 回复  |  直到 16 年前
        1
  •  6
  •   Steven Robbins    16 年前

    你可以通过挂起更改事件并将其更改回来来完成,但对我来说,这似乎有点臭:

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

        2
  •  4
  •   Gdeglin    16 年前

    有一种方法: http://www.thesorensens.org/2006/10/06/final-methods-in-ruby-prevent-method-override/

    它还被打包到一个名为“finalizer”(gem install finalizer)的gem中

    这将使用添加了方法的回调,并将新方法名与要生成的方法列表进行比较 final

        3
  •  1
  •   Mario Narcis Radoi    15 年前

    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.
    

        4
  •  0
  •   MVP    8 年前

    一种防止方法被子类重写的方法(但不建议这样做):

    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

    推荐文章