zoukankan      html  css  js  c++  java
  • 3-9《元编程》第3章Tuesday:methods

    第3章methods

     Ruby是动态语言,有静态语言实现不了的技巧。本章讲解代码的重构,把代码变得更简洁。

    3.2Dynamic Methods 

     3.21Calling Methods Dynamically

     Dynamic Dispatch(动态派发技巧):使用Object#send方法,方法名是send()的参数,可以在代码运行的最后一刻决定调用哪个方法。

    send(symbol[,args...]) -> obj  #string也行,会自动转换为symbol 

    send方法可以调用任何方法,包括私有方法。

    Pry的例子(Ruby的命令行解释权,功能强于默认的irb https://github.com/pry/pry

    Kernel#respond_to?   检测如Rry#memory_size= 这样的方法是否存在。

    respond_to?(symbol, include_all=false) → true or false

    Hash#merge! 

     3.22 Defining Methods Dynamically动态方法。

     使用Module#define_method()方法随时定义一个方法.代替def的重要原因是可以在运行时决定方法的名字。

    说明:Defines an instance method in the receiver.
    define_method(symbol, method) → symbol
    define_method(symbol) { block } → symbol
     实例:
    class Myclass
      define_method(:my_method){|my_arg| my_arg * 3}
    end
    obj = Myclass.new
    p obj.my_method(2)


     #########复杂的实例。

    class A

      def fred
        puts "In Fred"
      end
      def create_method(name, &block)
        self.class.send(:define_method, name, &block)
      end
      define_method(:wilma) { puts "Charge it!" }
    end
    class B < A
      define_method(:barney, instance_method(:fred))
    end
    a = B.new
    a.barney
    a.wilma
    a.create_method(:betty) { p "sad" }
    a.betty
    ##########结果:
    In Fred
    Charge it!
    "sad"
     

     3.23Refactoring the Computer Class

    第一步 添加动态派发Dynamic dispatch: 把重复的代码抽出来,放到该类的一个方法中用send方法来接收method名字作为参数。

    第二步 动态创建方法:define_method方法重构Computer类 

    第三步 内省introspection,缩减代码。

    代码: 

    class Computer
      def initialize(computer_id, data_source)
        @id = computer_id
        @data_source = data_source

        # introspection内省

        data_source.methods.grep(/^get_(.*)_info$/){Computer.define_component $1}   
      end
      def self.define_component(name)
        define_method(name) do
          info = @data_source.send "get_#{name}_info", @id 

          # get_#{name}_info是传进对象的类的方法。

          price = @data_source.send "get_#{name_price}", @id
          result = "#{name.capitalize}:#{info},#{price}"

          return "超支项目#{result}"  if price >= 100

          result #省略了return
        end
      end
    end
    my_computer = Computer.new(4, 从其他类传近来的实例对象)
    my_computer.cpu





    3.3method_missing方法

    动态代理和幽灵方法,解决代码繁复问题。 

     method_missing是BasicObject的私有实例方法。

     3.31 Overriding method_missing

    从新写method_missing方法让你可以调用实际并不存在的方法。被处理的消息,从调用者的角度看,和普通方法没区别,但实际receiver并没有对应的方法,这称为Ghose Method。

    class Lawyer
      def method_missing(method, *args)
        puts "You called: #{method}(#{args.join(', ')})"
        puts "You also passed it a block" if block_given?
      end
    end
    b = Lawyer.new
    b.talk('a', 'b', "c") do
      # a block
    end

    #*args代表多个参数。block_given?是kernel方法


    3.51BasicObject 

    拥有极少实例方法的类也叫blank Slate。BasicObject只有几个实例方法。 

    如果幽灵方法和真实方法的名字冲突,幽灵方法会被忽略。这时可以让创建的类继承BasicObject. 

    3.52删除方法

    Module#undef_method: 删除所以(包含继承)的方法

    Module#remove_method : 只删除receiver自己的方法。

    幽灵方法的重构:动态代理和白版类。

    class Computer < BasicObject
      def initialize(computer_id, data_source)
        @id = computer_id
        @data_source = data_source
      end
      def method_missing(name, *args)
        super unless @data_source.respond_to?("get_#{name}_info")
        info = @data_source.send("get_#{name}_info", @id)
        price = @data_source.send "get_#{name_price}", @id
        result = "#{name.capitalize}: #{info} ($#{price})"
        return "*#{result}" if price >= 100
        result
      end
    end


    3.61Dynamic Methods vs. Ghost Methods

    幽灵方法不是真正的方法,只是对方法调用的拦截。

    原则:在可以使用动态方法的时候,尽量使用动态方法;除非必须使用幽灵方法,否则尽量不用。 

  • 相关阅读:
    Java:IO流之字符流缓冲区详解
    Java:IO流之字符流Reader、Writer详解
    Java:IO流之字节流InputStream、OutputStream详解
    iOS:Git分布式版本控制器系统
    Java:日历类、日期类、数学类、运行时类、随机类、系统类
    Java:泛型
    Java:静态导入
    Java:集合for高级循环遍历
    一个相当好的状态机(DFA, 确定有限状态机)的编码实现,相当简洁漂亮
    android 开发必用的开源库
  • 原文地址:https://www.cnblogs.com/chentianwei/p/8532746.html
Copyright © 2011-2022 走看看