<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # Ruby 中的面向對象編程 > 原文: [https://zetcode.com/lang/rubytutorial/oop/](https://zetcode.com/lang/rubytutorial/oop/) 在 Ruby 教程的這一部分中,我們將討論 Ruby 中的面向對象編程。 編程語言具有過程編程,函數式編程和面向對象的編程范例。 Ruby 是一種具有某些函數式和過程特性的面向對象的語言。 面向對象編程(OOP)是一種使用對象及其相互作用設計應用和計算機程序的編程范例。 OOP 中的基本編程概念是: * 抽象 * 多態 * 封裝 * 繼承 抽象通過建模適合該問題的類來簡化復雜的現實。 多態是將運算符或函數以不同方式用于不同數據輸入的過程。 封裝對其他對象隱藏了類的實現細節。 繼承是一種使用已經定義的類形成新類的方法。 ## Ruby 對象 對象是 Ruby OOP 程序的基本構建塊。 對象是數據和方法的組合。 在 OOP 程序中,我們創建對象。 這些對象通過方法進行通信。 每個對象都可以接收消息,發送消息和處理數據。 創建對象有兩個步驟。 首先,我們定義一個類。 類是對象的模板。 它是一個藍圖,描述了類對象共享的狀態和行為。 一個類可以用來創建許多對象。 在運行時從類創建的對象稱為該特定類的實例。 ```ruby #!/usr/bin/ruby class Being end b = Being.new puts b ``` 在第一個示例中,我們創建一個簡單的對象。 ```ruby class Being end ``` 這是一個簡單的類定義。 模板的主體為空。 它沒有任何數據或方法。 ```ruby b = Being.new ``` 我們創建`Being`類的新實例。 為此,我們有`new`方法。 `b`變量存儲新創建的對象。 ```ruby puts b ``` 我們將對象打印到控制臺以獲取該對象的一些基本描述。 實際上,當我們打印對象時,我們將其稱為`to_s`方法。 但是我們還沒有定義任何方法。 這是因為創建的每個對象都繼承自基本`Object`。 它具有一些基本功能,這些功能在所有創建的對象之間共享。 其中之一是`to_s`方法。 ```ruby $ ./simple.rb #<Being:0x9f3c290> ``` 我們得到對象類名。 ## Ruby 構造器 構造器是一種特殊的方法。 創建對象時會自動調用它。 構造器不返回值。 構造器的目的是初始化對象的狀態。 Ruby 中的構造器稱為`initialize`。 構造器不返回任何值。 使用`super`方法調用父對象的構造器。 它們按繼承順序被調用。 ```ruby #!/usr/bin/ruby class Being def initialize puts "Being is created" end end Being.new ``` 我們有一個存在類。 ```ruby class Being def initialize puts "Being is created" end end ``` `Betweening`類具有一個名為`initialize`的構造方法。 它將消息打印到控制臺。 Ruby 方法的定義位于`def`和`end`關鍵字之間。 ```ruby Being.new ``` 創建`Being`類的實例。 創建對象時,將調用構造方法。 ```ruby $ ./constructor.rb Being is created ``` 這是程序的輸出。 對象的屬性是捆綁在該對象內部的數據項。 這些項目也稱為實例變量或成員字段。 實例變量是在類中定義的變量,該類中的每個對象都有一個單獨的副本。 在下一個示例中,我們初始化類的數據成員。 變量的初始化是構造器的典型工作。 ```ruby #!/usr/bin/ruby class Person def initialize name @name = name end def get_name @name end end p1 = Person.new "Jane" p2 = Person.new "Beky" puts p1.get_name puts p2.get_name ``` 在上面的 Ruby 代碼中,我們有一個帶有一個成員字段的`Person`類。 ```ruby class Person def initialize name @name = name end ``` 在`Person`類的構造器中,我們將一個`member`字段設置為一個值名稱。 名稱參數在創建時傳遞給構造器。 構造器是稱為`initialize`的方法,該方法在創建實例對象時被調用。 `@name`是一個實例變量。 實例變量在 Ruby 中以`@`字符開頭。 ```ruby def get_name @name end ``` `get_name`方法返回成員字段。 在 Ruby 中,成員字段只能通過方法訪問。 ```ruby p1 = Person.new "Jane" p2 = Person.new "Beky" ``` 我們創建`Person`類的兩個對象。 字符串參數傳遞給每個對象構造器。 名稱存儲在每個對象唯一的實例變量中。 ```ruby puts p1.get_name puts p2.get_name ``` 我們通過在每個對象上調用`get_name`來打印成員字段。 ```ruby $ ./person.rb Jane Beky ``` 我們看到了程序的輸出。 `Person`類的每個實例都有其自己的名稱成員字段。 我們可以創建對象而無需調用構造器。 Ruby 為此有一種特殊的`allocate`方法。 `allocate`方法為類的新對象分配空間,并且不會在新實例上調用`initialize`。 ```ruby #!/usr/bin/ruby class Being def initialize puts "Being created" end end b1 = Being.new b2 = Being.allocate puts b2 ``` 在示例中,我們創建兩個對象。 第一個對象使用`new`方法,第二個對象使用`allocate`方法。 ```ruby b1 = Being.new ``` 在這里,我們使用`new`關鍵字創建對象的實例。 調用構造器方法`initialize`,并將消息打印到控制臺。 ```ruby b2 = Being.allocate puts b2 ``` 在`allocate`方法的情況下,不調用構造器。 我們使用`puts`關鍵字調用`to_s`方法以顯示該對象已創建。 ```ruby $ ./allocate.rb Being created #<Being:0x8ea0044> ``` 在這里,我們看到了程序的輸出。 ## Ruby 構造器重載 構造器重載是在一個類中具有多種類型的構造器的能力。 這樣,我們可以創建具有不同數量或不同類型參數的對象。 Ruby 沒有我們從某些編程語言中知道的構造器重載。 可以使用 Ruby 中的默認參數值在某種程度上模擬此行為。 ```ruby #!/usr/bin/ruby class Person def initialize name="unknown", age=0 @name = name @age = age end def to_s "Name: #{@name}, Age: #{@age}" end end p1 = Person.new p2 = Person.new "unknown", 17 p3 = Person.new "Becky", 19 p4 = Person.new "Robert" p p1, p2, p3, p4 ``` 本示例說明了如何在具有兩個成員字段的`Person`類上模擬構造器重載。 如果未指定`name`參數,則使用字符串`"unknown"`。 對于未指定的年齡,我們為 0。 ```ruby def initialize name="unknown", age=0 @name = name @age = age end ``` 構造器有兩個參數。 它們具有默認值。 如果在創建對象時未指定自己的值,則使用默認值。 請注意,必須保留參數的順序。 首先是名字,然后是年齡。 ```ruby p1 = Person.new p2 = Person.new "unknown", 17 p3 = Person.new "Becky", 19 p4 = Person.new "Robert" p p1, p2, p3, p4 ``` 我們創建四個對象。 構造器采用不同數量的參數。 ```ruby $ ./consover.rb Name: unknown, Age: 0 Name: unknown, Age: 17 Name: Becky, Age: 19 Name: Robert, Age: 0 ``` 這是示例的輸出。 ## Ruby 方法 方法是在類主體內定義的函數。 它們用于通過對象的屬性執行操作。 在 OOP 范式的封裝概念中,方法至關重要。 例如,我們的`AccessDatabase`類中可能有一個`connect`方法。 我們無需告知該方法如何準確地連接到數據庫。 我們只需要知道它用于連接數據庫。 這對于劃分編程中的職責至關重要,尤其是在大型應用中。 在 Ruby 中,只能通過方法訪問數據。 ```ruby #!/usr/bin/ruby class Person def initialize name @name = name end def get_name @name end end per = Person.new "Jane" puts per.get_name puts per.send :get_name ``` 該示例顯示了兩種調用方法的基本方法。 ```ruby puts per.get_name ``` 常見的方法是在對象上使用點運算符,后跟方法名稱。 ```ruby puts per.send :get_name ``` 替代方法是使用內置的`send`方法。 它以方法的符號作為參數。 方法通常對對象的數據執行某些操作。 ```ruby #!/usr/bin/ruby class Circle @@PI = 3.141592 def initialize @radius = 0 end def set_radius radius @radius = radius end def area @radius * @radius * @@PI end end c = Circle.new c.set_radius 5 puts c.area ``` 在代碼示例中,我們有一個`Circle`類。 我們定義了兩種方法。 ```ruby @@PI = 3.141592 ``` 我們在`Circle`類中定義了`@@PI`變量。 它是一個類變量。 類變量以 Ruby 中的`@@`信號開頭。 類變量屬于類,而不屬于對象。 每個對象都可以訪問其類變量。 我們使用`@@PI`計算圓的面積。 ```ruby def initialize @radius = 0 end ``` 我們只有一個成員字段。 它是圓的半徑。 如果要從外部修改此變量,則必須使用公共可用的`set_radius`方法。 數據受到保護。 ```ruby def set_radius radius @radius = radius end ``` 這是`set_radius`方法。 它為`@radius`實例變量提供了一個新值。 ```ruby def area @radius * @radius * @@PI end ``` `area`方法返回圓的面積。 這是方法的典型任務。 它可以處理數據并為我們帶來一些價值。 ```ruby c = Circle.new c.set_radius 5 puts c.area ``` 我們創建`Circle`類的實例,并通過在圓對象上調用`set_radius`方法來設置其半徑。 我們使用點運算符來調用該方法。 ```ruby $ ./circle.rb 78.5398 ``` 運行示例,我們得到此輸出。 ## Ruby 訪問修飾符 訪問修飾符設置方法和成員字段的可見性。 Ruby 具有三個訪問修飾符:`public`,`protected`和`private`。 在 Ruby 中,所有數據成員都是私有的。 訪問修飾符只能在方法上使用。 除非我們另有說明,否則 Ruby 方法是公共的。 可以從類的定義內部以及從類的外部訪問`public`方法。 `protected`和`private`方法之間的區別很細微。 在類的定義之外都無法訪問它們。 只能在類本身內部以及繼承的或父類訪問它們。 請注意,與其他面向對象的編程語言不同,繼承在 Ruby 訪問修飾符中不扮演的角色。 只有兩件事很重要。 首先,如果我們在類定義的內部或外部調用方法。 其次,如果我們使用或不使用指向當前接收器的`self`關鍵字。 訪問修飾符可防止意外修改數據。 它們使程序更強大。 某些方法的實現可能會發生變化。 這些方法是很好的私有方法。 公開給用戶的接口僅應在確實必要時更改。 多年來,用戶習慣于使用特定的方法,并且通常不贊成向后兼容。 ```ruby #!/usr/bin/ruby class Some def method1 puts "public method1 called" end public def method2 puts "public method2 called" end def method3 puts "public method3 called" method1 self.method1 end end s = Some.new s.method1 s.method2 s.method3 ``` 該示例說明了公共 Ruby 方法的用法。 ```ruby def method1 puts "public method1 called" end ``` 即使我們未指定`public`訪問修飾符,`method1`也是公共的。 這是因為如果沒有另外指定,默認情況下方法是公共的。 ```ruby public def method2 puts "public method2 called" end ... ``` `public`關鍵字后面的方法是公共的。 ```ruby def method3 puts "public method3 called" method1 self.method1 end ``` 從公共`method3`內部,我們調用帶有和不帶有`self`關鍵字的其他公共方法。 ```ruby s = Some.new s.method1 s.method2 s.method3 ``` 公共方法是唯一可以在類定義之外調用的方法,如下所示。 ```ruby $ ./public_methods.rb public method1 called public method2 called public method3 called public method1 called public method1 called ``` 運行示例,我們將獲得以下輸出。 下一個示例著眼于私有方法。 ```ruby #!/usr/bin/ruby class Some def initialize method1 # self.method1 end private def method1 puts "private method1 called" end end s = Some.new # s.method1 ``` 私有方法是 Ruby 中最嚴格的方法。 只能在類定義內調用它們,而不能使用`self`關鍵字。 ```ruby def initialize method1 # self.method1 end ``` 在方法的構造器中,我們稱為私有`method1`。 帶有`self`的方法被注釋。 接收者無法指定私有方法。 ```ruby private def method1 puts "private method1 called" end ``` 關鍵字`private`之后的方法在 Ruby 中是私有的。 ```ruby s = Some.new # s.method1 ``` 我們創建`Some`類的實例。 禁止在類定義之外調用該方法。 如果我們取消注釋該行,則 Ruby 解釋器將給出錯誤。 ```ruby $ ./private_methods.rb private method called ``` 示例代碼的輸出。 最后,我們將使用受保護的方法。 Ruby 中的保護方法和私有方法之間的區別非常微妙。 受保護的方法就像私有的。 只有一個小差異。 可以使用指定的`self`關鍵字來調用它們。 ```ruby #!/usr/bin/ruby class Some def initialize method1 self.method1 end protected def method1 puts "protected method1 called" end end s = Some.new # s.method1 ``` 上面的示例顯示了使用中的受保護方法。 ```ruby def initialize method1 self.method1 end ``` 可以使用`self`關鍵字來調用受保護的方法。 ```ruby protected def method1 puts "protected method1 called" end ``` 受保護的方法前面帶有`protected`關鍵字。 ```ruby s = Some.new # s.method1 ``` 不能在類定義之外調用受保護的方法。 取消注釋該行將導致錯誤。 ## Ruby 繼承 繼承是一種使用已經定義的類形成新類的方法。 新形成的類稱為派生的類,我們派生的類稱為基類。 繼承的重要好處是代碼重用和降低程序的復雜性。 派生類(后代)將覆蓋或擴展基類(祖先)的功能。 ```ruby #!/usr/bin/ruby class Being def initialize puts "Being class created" end end class Human < Being def initialize super puts "Human class created" end end Being.new Human.new ``` 在此程序中,我們有兩個類:基礎`Being`類和派生的`Human`類。 派生類繼承自基類。 ```ruby class Human < Being ``` 在 Ruby 中,我們使用`<`運算符創建繼承關系。 `Human`類繼承自`Being`類。 ```ruby def initialize super puts "Human class created" end ``` `super`方法調用父類的構造器。 ```ruby Being.new Human.new ``` 我們實例化`Being`和`Human`類。 ```ruby $ ./inheritance.rb Being class created Being class created Human class created ``` 首先創建`Being`類。 派生的`Human`類還調用其父級的構造器。 對象可能涉及復雜的關系。 一個對象可以有多個祖先。 Ruby 有一個方法`ancestors`,它提供了特定類的祖先列表。 每個 Ruby 對象自動是`Object`和`BasicObject`類以及`Kernel`模塊的后代。 它們內置在 Ruby 語言的核心中。 ```ruby #!/usr/bin/ruby class Being end class Living < Being end class Mammal < Living end class Human < Mammal end p Human.ancestors ``` 在此示例中,我們有四個類:`Human`是`Mammal`,`Living`和`Being`。 ```ruby p Human.ancestors ``` 我們打印人類類的祖先。 ```ruby $ ./ancestors.rb [Human, Mammal, Living, Being, Object, Kernel, BasicObject] ``` 人類類具有三個習俗和三個內置祖先。 接下來是一個更復雜的示例。 ```ruby #!/usr/bin/ruby class Being @@count = 0 def initialize @@count += 1 puts "Being class created" end def show_count "There are #{@@count} beings" end end class Human < Being def initialize super puts "Human is created" end end class Animal < Being def initialize super puts "Animal is created" end end class Dog < Animal def initialize super puts "Dog is created" end end Human.new d = Dog.new puts d.show_count ``` 我們有四個類。 繼承層次更加復雜。 `Human`和`Animal`類繼承自`Being`類。 `Dog`類直接繼承自`Animal`類,并且進一步繼承自`Being`類。 我們還使用一個類變量來計算創建的生物的數量。 ```ruby @@count = 0 ``` 我們定義一個類變量。 類變量以`@@`信號開頭,并且它屬于該類,而不是該類的實例。 我們用它來計算創造的生物數量。 ```ruby def initialize @@count += 1 puts "Being class created" end ``` 每次實例化`Being`類時,我們都會將`@@count`變量加 1。 這樣,我們就可以跟蹤創建的實例數。 ```ruby class Animal < Being ... class Dog < Animal ... ``` `Animal`繼承自`Being`,`Dog`繼承自`Animal`。 另外,`Dog`也繼承自`Being`。 ```ruby Human.new d = Dog.new puts d.show_count ``` 我們從`Human`和`Dog`類創建實例。 我們在`Dog`對象上調用`show_count`方法。 `Dog`類沒有這種方法。 然后調用祖父級`Being`的方法。 ```ruby $ ./inheritance2.rb Being class created Human is created Being class created Animal is created Dog is created There are 2 beings ``` `Human`對象調用兩個構造器。 `Dog`對象調用三個構造器。 有兩個實例化的存在。 繼承在方法和數據成員的可見性中不起作用。 與許多常見的面向對象的編程語言相比,這是一個明顯的區別。 在 C# 或 Java 中,公共和受保護的數據成員和方法是繼承的。 私有數據成員和方法不是。 與此相反,私有數據成員和方法也在 Ruby 中繼承。 數據成員和方法的可見性不受 Ruby 中繼承的影響。 ```ruby #!/usr/bin/ruby class Base def initialize @name = "Base" end private def private_method puts "private method called" end protected def protected_method puts "protected_method called" end public def get_name return @name end end class Derived < Base def public_method private_method protected_method end end d = Derived.new d.public_method puts d.get_name ``` 在示例中,我們有兩個類。 `Derived`類繼承自`Base`類。 它繼承了所有三種方法和一個數據字段。 ```ruby def public_method private_method protected_method end ``` 在`Derived`類的`public_method`中,我們調用一種私有方法和一種受保護方法。 它們在父類中定義。 ```ruby d = Derived.new d.public_method puts d.get_name ``` 我們創建`Derived`類的實例。 我們稱為`public_method`,也稱為`get_name`,它返回私有`@name`變量。 請記住,所有實例變量在 Ruby 中都是私有的。 無論`@name`是私有的還是在父類中定義的,`get_name`方法都會返回該變量。 ```ruby $ ./inheritance3.rb private method called protected_method called Base ``` 該示例的輸出確認,在 Ruby 語言中,子對象從其父級繼承了`public`,`protected`,`private`方法和`private`成員字段。 ## Ruby `super`方法 `super`方法在父類的類中調用相同名稱的方法。 如果該方法沒有參數,它將自動傳遞其所有參數。 如果我們寫`super()`,則不會將任何參數傳遞給父方法。 ```ruby #!/usr/bin/ruby class Base def show x=0, y=0 p "Base class, x: #{x}, y: #{y}" end end class Derived < Base def show x, y super super x super x, y super() end end d = Derived.new d.show 3, 3 ``` 在示例中,我們在層次結構中有兩個類。 它們都有顯示方法。 派生類中的`show`方法使用`super`方法調用基類中的`show`方法。 ```ruby def show x, y super super x super x, y super() end ``` 不帶任何參數的`super`方法使用傳遞給`Derived`類的`show`方法的參數調用父級的`show`方法:此處,`x = 3`和`y = 3`。 `super()`方法不將任何參數傳遞給父級的`show`方法。 ```ruby $ ./super.rb "Base class, x: 3, y: 3" "Base class, x: 3, y: 0" "Base class, x: 3, y: 3" "Base class, x: 0, y: 0" ``` 這是示例的輸出。 這是 Ruby 中 OOP 描述的第一部分。
                  <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>

                              哎呀哎呀视频在线观看