第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Ruby 的類

我們在之前的章節(jié)講了 Ruby 的很多對象,學(xué)會了如何使用簡單的對象(例如:數(shù)字和字符串)以及數(shù)據(jù)結(jié)構(gòu)數(shù)組和哈希來完成一些工作,了解如何使用方法,做好了充足的準(zhǔn)備。本章中,我會為大家講解 Ruby 的類,如何創(chuàng)建一個類以及類的實例,以及類的實例方法如何創(chuàng)建。

1. 什么是 Ruby 的類

當(dāng) Ruby 運(yùn)行程序的時候,會創(chuàng)建一個空間,我們使用具體的事物對這些空間進(jìn)行填充,我們可以調(diào)用這些事物的方法去做某些事情。同時,每個具體的事物(對象)都是一般思想或類型的實例,這些思想稱為類。

在終端中我們可以通過class方法來查看對象所屬的類。

實例:

"Hello World".class

# ---- 輸出結(jié)果 ----
String

對象是類的具體實例(表現(xiàn))。

我們還可以使用is_a?的方法來具體詢問對象是否屬于某個類:

實例:

"Hello World".is_a?(String)

# ---- 輸出結(jié)果 ----
true

類是用于對象的藍(lán)圖。類具有很多特性,每個類定義了許多方法,這些方法特定用于此類事物(例如:字符串),每次從類創(chuàng)建對象的時候,每個對象都會擁有類給他們的這些方法,也可以說,對象從類繼承了方法。

2. 一步一步創(chuàng)建類

2.1 定義一個類

首先讓我們創(chuàng)建一個Calculator的類,并逐步為它添加方法。

實例:

class Calculator
end

解釋:我們使用關(guān)鍵字class,名稱和關(guān)鍵字end定義一個類。

注意事項:我們定義類的時候,首字母一定要大寫開頭,否則會出現(xiàn)報錯。同樣對于由幾個單詞命名的類,我們應(yīng)該使用大寫字母分隔這些單詞,例如:RubyStudyGroup,而對于變量名和方法名,我們要使用下劃線,且所有內(nèi)容都應(yīng)該小寫,例如:local_variablemethod_name。

2.2 創(chuàng)建一個實例

因為我們定義了一個完整的有效類,所以我們可以創(chuàng)建一個Calculator實例,下面是創(chuàng)建一個Calculator實例的方法。

Calculator.new

# ---- 輸出結(jié)果 ----
#<Calculator:0x00007fb4132c0af0>

解釋new方法是在類Calculator上定義的(Calculator它本身既是一個類也是一個對象,還記得我們說Ruby中所有東西都是對象嗎。所以它也可以擁有方法)。此方法創(chuàng)建了一個新的實例,并返回它。

格式#<...>告訴您此對象不是簡單的東西,比如數(shù)字,字符串或數(shù)組。它只是告訴您類的名稱,Calculator以及Ruby分配給該對象的內(nèi)部ID。

每個對象都有自己唯一的內(nèi)部對象ID,當(dāng)我在計算機(jī)上運(yùn)行此代碼時,Ruby分配的ID為0x00007fb4132c0af0。如果您運(yùn)行它,將會得到不同的結(jié)果。實際上,在大多數(shù)情況下,您可以忽略此ID。另外,我們可以檢查我們的新計算器實例確實是類Calculator的實例。

實例:

class Calculator
end
calculator = Calculator.new
puts calculator.class
puts calculator.is_a?(Calculator)

# ---- 輸出結(jié)果 ----
Calculator
true

2.3 定義實例方法

我們可以在類和對象上定義和調(diào)用方法。類上可用的方法稱為類方法,實例上可用的方法稱為實例方法。剛才我們定義了一個類,現(xiàn)在讓我們?yōu)樗黾右粋€sum方法。

實例:

class Calculator
  def sum(number, other)
    number + other
  end
end

解釋:我們在類中定義一個方法,即為這個類的實例方法。

注意事項:我們在定義實例方法的時候記得要縮進(jìn) 2 個空格,表明sum屬于Calculator類。這是一種規(guī)范。

那么我們?nèi)绾问褂眠@個定義的sum實例方法呢?

我們可以實例化一個Calculator,然后調(diào)用這個方法。

實例:

calculator = Calculator.new
puts calculator.sum(2, 3)

# ---- 輸出結(jié)果 ----
5

2.4 初始化對象

在我們向類添加任何行為(方法)之前,我們希望能夠為其提供一些初始數(shù)據(jù)。

讓我們重新定義一個Person類。

實例:

class Person
end

在我們的情況下,我們希望該人知道自己的名字。

實例:

class Person
  def initialize(name)
  end
end

解釋:您會看到我們?yōu)檫@個類增加了一個名為initialize的方法,并且可以接收一個name參數(shù)。當(dāng)類方法new創(chuàng)建對象時,將在內(nèi)部調(diào)用特殊的initialize方法。

我們可以通過以下這種方式將名稱傳遞給類的內(nèi)部:

p Person.new("Andrew")

# ---- 輸出結(jié)果 ----
#<Person:0x00007fb41326b118>

2.5 使用實例變量記錄初始化屬性

繼續(xù)我們剛才做的事,我們想在實例化對象的時候,讓對象保留自己初始化的名稱,這時我們用到了實例變量instance variable

實例:

class Person
  def initialize(name)
    @name = name
  end
end

解釋:我們將name的值賦予了實例變量@name,它的作用域為整個在對象范圍內(nèi)的任何位置。

此時我們再次實例化Person類:

p Person.new("Andrew")

#---- 輸出結(jié)果 ----
#<Person:0x00007fb41321add0 @name="Andrew">

此時,我們創(chuàng)建的Person對象中有了一個實例變量@name,它的值為Andrew。

2.6 屬性讀取器(getter)

我們已經(jīng)創(chuàng)建了一個名為 Andrew 的Person對象,那么如何獲取它的名字呢。

實例:

class Person
  def initialize(name)
    @name = name
  end
  
  def name
    @name
  end
end

此時我們可以通過向?qū)ο蟀l(fā)送name的消息,獲取對應(yīng)的信息。

實例:

person = Person.new("Andrew")
person.name

#---- 輸出結(jié)果 ----
"Andrew"

解釋:我們定義了一個方法name,它返回了實例變量@name,由此創(chuàng)建了一個屬性讀取器。屬性讀取器返回實例變量的值,也可以說,屬性讀取器公開了實例變量,讓所有的人都可以讀取它。

除此之外我們還有一種簡單的寫法,實現(xiàn)@name的讀?。?/p>

class Person
  attr_reader :name
  def initialize(name)
    @name = name
  end
end

和上面的操作是等效的。

2.7 屬性設(shè)置器(setter)

現(xiàn)在我們添加一個功能,一個人不僅要有名稱,也要能設(shè)置密碼,這個密碼我們希望在Person對象被實例后才被告知,讓我們進(jìn)一步改變這個類。

class Person
  def initialize(name)
    @name = name
  end

  def name
    @name
  end

  def password=(password)
    @password = password
  end
end

解釋:如您所見,方法password =只能執(zhí)行一個參數(shù)(稱為password),并將此局部變量的值分配給實例變量@password,其他什么也不做。

現(xiàn)在讓我們?yōu)橐粋€Person對象添加密碼。

實例:

person = Person.new("Andrew")
person.password=("super password")
p person

#<Person:0x00007fb413154810 @name="Andrew", @password="super password">

解釋:在幕后,Ruby 在運(yùn)行代碼時將person.password ="something"行轉(zhuǎn)換為person.password =("something"),這僅調(diào)用方法password=,在右側(cè)傳遞的值作為參數(shù),這只是另一種方法。

同樣我們也有一種簡寫方法給屬性設(shè)置器:

class Person
  attr_writer :password
  def initialize(name)
    @name = name
  end

  def name
    @name
  end

end

2.8 對象作用域

您可以通過對象上的任何方法訪問:

  • 所有局部變量;

  • 所有實例變量;

  • 所有對象的方法。

讓我們寫一個greet方法來為您展示。

實例:

class Person
  
  def name
    @name
  end

  def greet(other)
    name = other.name
    puts "Hi " + name + "! My name is " + @name + "."
  end
  
end

boy = Person.new("Andrew")
girl = Person.new("Alice")

boy.greet(girl)

#---- 輸出結(jié)果 ----
Hi Alice! My name is Andrew.

解釋:這是一個對象交互的例子,我們定義了一個greet方法,這個里面調(diào)用了@name實例變量,other是一個參數(shù),代表Person的對象。

注意事項:當(dāng) Ruby 找到一個標(biāo)識符時,Ruby 首先尋找一個局部變量,然后尋找一個方法。上述代碼name沒有調(diào)用實例方法name而是取的other.name的值就是因為這個原因。

2.9 self

每個對象都通過調(diào)用 self 的方式以每種方法認(rèn)識自己。這是 Ruby 中的一個特殊關(guān)鍵字,它的意思是對象本身。

class Person
  def initialize(name)
    @name = name
    p self
  end
end

person = Person.new("Anja")
p person

#---- 輸出結(jié)果 ----
#<Person:0x007f9994972428 @name="Anja">
#<Person:0x007f9994972428 @name="Anja">

解釋:如您所見,我們兩次輸出相同的對象。一次在初始化方法中使用p self,一次在外部范圍中使用p person。您還可以看到,這兩個實例的神秘對象 ID 相同。因此我們可以知道它確實是同一對象。

所以,之前的方法我們可以這樣修改:

class Person
  def name
    @name
  end

  def greet(other)
    name = other.name
    puts "Hi " + name + "! My name is " + self.name + "."
  end
end

boy = Person.new("Andrew")
girl = Person.new("Alice")

boy.greet(girl)

#---- 輸出結(jié)果 ----
Hi Alice! My name is Andrew.

解釋:現(xiàn)在,我們再次在兩個不同的對象上調(diào)用方法name。當(dāng) Ruby 看到self時,它知道我們正在引用當(dāng)前的Person對象,并在其上調(diào)用方法name

注意事項:self是一個關(guān)鍵字并不是一個方法,我們從下面的代碼可以證明。

person = Person.new("Andrew")
p person.self

#---- 輸出結(jié)果 ----
NoMethodError (undefined method `self' for #<Person:0x00007fb413290bc0 @name="Andrew">)

關(guān)鍵字是在 Ruby 中具有特殊含義的單詞,例如class,defendself。

2.10 類方法(Class Method

類方法的格式為:類名.方法名(),通俗來說就是類名調(diào)用的方法,在其他語言中也稱為靜態(tài)方法(Static Method)。

現(xiàn)在我們要輸出Person類英語和中文名稱,對Person類要這樣修改。

實例:

class Person
  def self.cn_name
    '人'
  end
  
  def self.en_name
    'Person'
  end
end

puts Person.cn_name
puts Person.en_name

#---- 輸出結(jié)果 ----Person

解釋: 上述我們定義了兩個類方法,一個為cn_name,一個為en_name,我們使用Person.cn_namePerson.en_name來調(diào)用這兩個方法。

除此之外,我們還可以使用另外一種寫法:

class Person
  class << self
    def cn_name
      '人'
    end

    def en_name
      'Person'
    end
  end
end

puts Person.cn_name
puts Person.en_name

解釋:這種寫法在單件類章節(jié)中會詳細(xì)講解,可以將它看成在一個類中定義多個類方法的一種便捷辦法。

假如我們要在類的外面定義類方法還可以這樣寫:

class Person
end

def Person.cn_name
  '人'
end

def Person.en_name
  'Person'
end

puts Person.cn_name
puts Person.en_name

#---- 輸出結(jié)果 ----Person

Tips:創(chuàng)建了一個類的時候,類方法和類的作用域內(nèi)(非實例方法部分),self表示的是類本身。

實例:

class Person
  puts "in class: #{self}"
  puts self == Person
  def self.cn_name
    puts "in class method: #{self}"
    puts self == Person
  end
end

#---- 輸出結(jié)果 ----
in class: Person
true
in class method: Person
true

3. 小結(jié)

本章中我們學(xué)習(xí)了如何創(chuàng)建一個 Ruby 的類,如何定義一個類、創(chuàng)建一個實例、定義實例方法、初始化對象、使用實例變量記錄、初始化屬性、屬性讀取器、屬性設(shè)置器、對象作用域以及了解了 self 的含義。