<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## 25.元編程 元編程是使程序編寫程序的藝術。 也就是說,在運行時,程序可以根據情況進行自我修改。 讓我們在本章中了解一下。 ### 25.1。 發送 Ruby 有一個功能強大的方法`send`。 也就是說,如果對象`p`具有方法`name`,則在 ruby 中我們可以使用`p.name`對其進行調用,或者還有另一種方法來調用它。 我們用`p.send(:name)`或`p.send("name")`稱呼它。 那么,這有什么用? 這樣做的用途是,你可以從用戶輸入或收到的其他輸入中確定要調用的函數。 讓我們看一個基本的例子。 在文本編輯器中鍵入以下程序 [send.rb](code/send.rb) 并運行它。 ```rb class Person attr_accessor :name def speak "Hello I am #{@name}" end end p = Person.new p.name = "Karthik" puts p.send(:speak) ``` 輸出量 ```rb Hello I am Karthik ``` 好的,正如你在突出顯示的代碼 p.send(:spe??ak)中所看到的那樣,我們正在使用 send 方法調用 Person 類的實例 p 的語音功能。 現在就發送。 興奮起來!!! 告知你正在學習元編程,并開始向同事吹牛。 好吧,希望你吹牛。 現在讓我們來看一下`send`函數的一些更實際的例子。 輸入示例 [send_1.rb](code/send_1.rb) 并執行 ```rb # send_1.rb class Student attr_accessor :name, :math, :science, :other end s = Student.new s.name = "Zigor" s.math = 100 s.science = 100 s.other = 0 print "Enter the subject who's mark you want to know: " subject = gets.chop puts "The mark in #{subject} is #{s.send(subject)}" ``` Output ```rb Enter the subject who's mark you want to know: math The mark in math is 100 ``` 因此,在該計劃中,我們有一個名為`Student`的類,我們創建了一個學生,該學生在數學,科學和其他科目上的分數分別為 100、100 和零。 我們要求用戶在以下語句中輸入需要知道其標記的主題,并將其放入名為主題的變量中 ```rb print "Enter the subject who's mark you want to know: " subject = gets.chop ``` 現在看到這一行: ```rb puts "The mark in #{subject} is #{s.send(subject)}" ``` 只需注意`s.send(subject)`部分,我們就在這里,而不是使用案例或其他 if 或條件來檢查主題是什么,然后根據其調用適當的方法,我們只需將用戶輸入傳遞給`s.send`,然后它將調用適當的方法 并返回值。 你沒看到魔法嗎? ### 25.2。 方法缺失 假設你有一個僅包含某些方法的類,并且如果程序員調用了其他瘋狂的方法,并且想要捕獲它并查看它是否仍然可以使用,則可以使用`method_missing`方法捕獲該方法 和其他東西。 讓我們看一下有關方法缺失的程序。 在測試編輯器中鍵入程序 [method_missing.rb](code/method_missing.rb) 并執行 ```rb # method_missing.rb class Something def method_missing method, *args, &block puts "You called: #{method}" p args block.call 7 end end s = Something.new s.call_method "boo", 5 do |x| x.times{ puts "in block" } end ``` Output ```rb You called: call_method ["boo", 5] in block in block in block in block in block in block in block ``` 讓我們看看該程序的工作原理,在`s = Something.new`行中,我們創建了`Something`類的新實例變量`s`。 然后在下一行中執行`s.call_method "boo", 5`,在此行中,我們在`s`上調用一個名為`call_method`的方法,如果查看類`Something`,你會注意到在其中沒有稱為 call_method 的方法或函數 它,但程序不會拋出錯誤,異常或其他任何信息。 好吧,發生了什么事? 如果你注意到 Something 類,你將看到一個名為 method_missing 的方法,該方法已實現,如下所示 ```rb def method_missing method, *args, &block puts "You called: #{method}" p args block.call 7 end ``` 此方法接受三個參數,在我們的代碼中,我們已將這些參數命名為`method`,`*args`和`&block`。 該方法接受方法名稱,該名稱是在對象`s`上調用的方法的名稱,`*args`具有傳遞給該方法的屬性,在本例中,其`call_method`和傳遞的屬性為`“boo”` 和`5`。 `&block`接受已傳遞的任何塊。 如果你看到下面的`s`,我們將其稱為`call_method` ```rb s.call_method "boo", 5 do |x| x.times{ puts "in block" } end ``` 我們正在將一個塊傳遞給`call_method`和`end`包圍的`call_method`函數。 在該塊內部,我們使用變量`x`并對其進行一些操作。 `&block`捕獲了整個塊。 最后,我們打印使用語句`p args`傳遞的參數(請注意,此處未使用`*args`),并使用`block.call 7`調用了該塊(請注意,此處使用了塊而不是&塊)。 method_missing 定義。 值`7`被傳遞到塊中的變量`x`。 現在讓我們看看如何使用缺少方法。 假設我們有一個名為`Person`的類,它具有兩個名為`name`和`age`的屬性,請參見下面的代碼并執行它 ```rb # method_missing_in_action.rb class Person attr_accessor :name, :age def initialize name, age @name, @age = name, age end def method_missing method_name method_name.to_s.match(/get_(\w+)/) eval("self.#{$1}") end end person = Person.new "Zigor", "67893" puts "#{person.get_name} is #{person.get_age} years old" ``` Output ```rb Zigor is 67893 years old ``` 在上面的代碼中,看到突出顯示的行`puts "#{person.get_name} is #{person.get_age} years old"`,我們稱其屬性與 person.name 和`person.age`不同,而是使用`person.get_name`和`person.get_age`。 現在`Person`類中沒有`get_name`和`get_age`方法,而是代碼在這里結束 ```rb def method_missing method_name method_name.to_s.match(/get_(\w+)/) eval("self.#{$1}") end ``` 在方法中缺少方法。 看一下代碼,在`method_name.to_s.match(/get_(\w+)/)`這一行中,我們提取與`get_`關聯的任何方法,然后在此語句中將提取的術語稱為`eval("self.#{$1}")`。 如果你無法理解這些內容,則可能必須閱讀[正則表達式](#_regular_expressions)一章。 現在如何實際使用它,例如,你可以擁有一個`get_db_&lt;method name&gt;`,你可以在其中從數據庫中獲取值,或者說`store_db_&lt;method name&gt;(values…?.)`,你可以在其中捕獲它并將其存儲在數據庫中。 ### 25.3。 定義方法 我們將在本節中了解如何在類中定義方法。 在下面輸入程序并執行 ```rb # define_method.rb class Square define_method :area do |side| side * side end end s = Square.new puts s.area 5 ``` Output ```rb 25 ``` 好的,所以輸出為 25。 如果你注意到程序 [define_method.rb](code/define_method.rb) ,你會注意到,在上面的幾行中,我們正在使用此尷尬的語句定義名為 area 的方法,如下所示 ```rb define_method :area do |side| side * side end ``` 你可能會想到為什么我們不這樣做: ```rb def area side side * side end ``` 是的,但是讓我們考慮一下可以動態定義方法的情況。 ```rb # define_method_dynamic.rb Book_hash = {author: "Zigor", title: "I Love Ruby", page: 95} class Book Book_hash.each do |key, value| define_method key do value end end end b = Book.new puts "#{b.author} has written a book named #{b.title}" ``` Output ```rb Zigor has written a book named I Love Ruby ``` 因此,在上面的程序中,我們有兩個突出顯示的部分,第一個是`Book_hash = {author: "Zigor", title: "I Love Ruby", page: 95}`,在這里是分配給哈希值的常量。 在現實世界中,它可能是一個從文件動態加載一些哈希值的變量。 在課堂書中,你會看到以下幾行: ```rb Book_hash.each do |key, value| define_method key do value end end ``` 我們在每個哈希值中取值,并使用其鍵定義方法,然后該方法返回該值。 因此,當我們說`b = Book.new`時,我們現在已經有名為`author`,`title`和`page`的函數,它們分別返回`“Zigor”`,`“I Love Ruby”`和`95`。 對于此語句,`puts "#{b.author} has written a book named #{b.title}"`進行了解釋。 ### 25.4。 等級評估 假設你有一個實例對象,你想在其類中添加一些內容,可以使用一種名為`class_eval`的方法,下面舉一個例子。 在文本編輯器中鍵入以下程序并執行。 ```rb # class_eval.rb class Animal end dog = Animal.new dog.class.class_eval do def say_something "I am a dog" end end pig = Animal.new puts pig.say_something ``` Output ```rb I am a dog ``` 查看下面顯示的代碼。 因此,你具有變量`dog`,它是`Animal`的實例。 可以說,在程序中突然我們決定在`dog`的類中添加`say_something`的方法,即`Animal`,我們要做的就是在`class_eval`塊中編寫該方法,如下所示 ```rb dog.class.class_eval do def say_something "I am a dog" end end ``` 在上面的程序中,我們使用`dog.class`獲得`dog`的類,并對其進行調用`class_eval`,其后是`do` `end`塊,在其中定義要附加到[[ `dog`。 在其中定義方法`say_something`。 現在讓我們說我們還有另一個名為`pig`的變量,它是`Animal`的實例,我們稱之為`pig.say_something`,它也響應! 因此,我們修改了類`Animal`。 ### 25.5。 實例評估 在`class_eval`中,我們看到可以將方法添加到可以由其實例訪問的類中。 `instance_eval`與之相反。 不,我們不會刪除方法:D,但這會將類方法添加到調用類中。 讓我們來看一個例子 ```rb # instance_eval.rb class Square end Square.instance_eval do def who_am_i puts "I am Square class" end end Square.who_am_i ``` Output ```rb I am Square class ``` 在上面的示例中,請看以下代碼: ```rb Square.instance_eval do def who_am_i puts "I am Square class" end end ``` 我們要做的就是在一個類上調用`instance_eval`,并且在一個塊內,我們需要編寫將成為類方法的代碼。 我們定義了一個函數`who_am_i`,其安靜程度等同于鍵入此 ```rb class Square def self.who_am_i puts "I am Square class" end end ``` 當我們調用`Square.who_am_i`時,該方法將忠實地響應。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看