Ruby是純面向?qū)ο蟮恼Z言,所有項目似乎要Ruby中為一個對象。Ruby中的每個值是一個對象,即使是最原始的東西:字符串,數(shù)字甚至true和false。即使是一個類本身是一個對象,它是Class類的一個實例。本章將通過所有功能涉及到Ruby的面向?qū)ο蟆?/p>
類是用來指定對象的形式,它結(jié)合了數(shù)據(jù)表示和方法操縱這些數(shù)據(jù),轉(zhuǎn)換成一個整齊的包。在一個類的數(shù)據(jù)和方法,被稱為類的成員。
Ruby類的定義:
定義一個類,定義的數(shù)據(jù)類型的草圖。 這實際上并不定義任何數(shù)據(jù),但它定義的類名字的意思什么,即是什么類的對象將包括這樣一個對象上執(zhí)行什么操作可以。
類定義開始與關(guān)鍵字class類名和 end 分隔。例如,我們定義Box類使用class關(guān)鍵字如下:
class Box
code
end
名稱必須以大寫字母開始,按照約定名稱中包含多個單詞,每個單詞沒有分隔符(駝峰式)一起執(zhí)行。
定義Ruby的對象:
類為對象的藍(lán)圖,所以基本上是一個從一個類對象被創(chuàng)建。我們聲明一個類的對象使用new關(guān)鍵字。下面的語句聲明了兩個對象,Box 類:
box1 = Box.new
box2 = Box.new
initialize方法:
initialize方法是一個標(biāo)準(zhǔn)的Ruby類的方法,和其它面向?qū)ο缶幊陶Z言的構(gòu)造方法有相同的方式工作。 initialize方法是有用的,在創(chuàng)建對象的時候,一些類變量初始化。這種方法可能需要的參數(shù)列表,它像其他Ruby之前的方法用def關(guān)鍵字定義,如下所示:
class Box
def initialize(w,h)
@width, @height = w, h
end
end
實例變量:
實例變量是類的一種屬性,一旦我們使用的類對象被創(chuàng)建的對象的屬性。每個對象的屬性被分別賦值的并與其它對象共享,它們在類的內(nèi)部使用@操作符訪問,但訪問類之外的,我們使用的公共方法被稱為訪問器方法。如果我們把上述定義的類 Box,然后 @width 和 @height 類 Box實例變量。
class Box
def initialize(w,h)
# assign instance avriables
@width, @height = w, h
end
end
訪問器和setter方法:
為了外部能訪問類的變量,它們必須定義存取器方法,這些存取器方法也被稱為getter方法。下面的例子演示了如何使用訪問器方法:
#!/usr/bin/ruby -w
# define a class
class Box
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# accessor methods
def printWidth
@width
end
def printHeight
@height
end
end
# create an object
box = Box.new(10, 20)
# use accessor methods
x = box.printWidth()
y = box.printHeight()
puts "Width of the box is : #{x}"
puts "Height of the box is : #{y}"
當(dāng)上面的代碼執(zhí)行時,它會產(chǎn)生以下結(jié)果:
Width of the box is : 10
Height of the box is : 20
類似的存取方法用于訪問的變量值,Ruby提供了一種方法來從類的外部設(shè)置這些變量的值,那就是setter方法??,定義如下:
#!/usr/bin/ruby -w
# define a class
class Box
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# accessor methods
def getWidth
@width
end
def getHeight
@height
end
# setter methods
def setWidth=(value)
@width = value
end
def setHeight=(value)
@height = value
end
end
# create an object
box = Box.new(10, 20)
# use setter methods
box.setWidth = 30
box.setHeight = 50
# use accessor methods
x = box.getWidth()
y = box.getHeight()
puts "Width of the box is : #{x}"
puts "Height of the box is : #{y}"
當(dāng)上面的代碼執(zhí)行時,它會產(chǎn)生以下結(jié)果:
Width of the box is : 30
Height of the box is : 50
實例方法:
也以同樣的方式,因為我們使用def關(guān)鍵字定義其他方法,并按下圖所示僅對使用一個類的實例,它們可以被用來定義該實例方法。它們的功能不局限于訪問實例變量,他們也可以按要求做更多的事情。
#!/usr/bin/ruby -w
# define a class
class Box
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# instance method
def getArea
@width * @height
end
end
# create an object
box = Box.new(10, 20)
# call instance methods
a = box.getArea()
puts "Area of the box is : #{a}"
當(dāng)上面的代碼執(zhí)行時,它會產(chǎn)生以下結(jié)果:
類的方法和變量:
類變量是一個變量,這是一個類的所有實例之間共享。該變量是一個實例,它是可訪問對象實例。兩個@字符類變量帶有前綴(@@)。在類定義類變量必須初始化,如下所示。
類方法的定義使用:def self.methodname() 以 end 字符結(jié)束,將被稱為使用classname.methodname類名,在下面的例子所示:
#!/usr/bin/ruby -w
class Box
# Initialize our class variables
@@count = 0
def initialize(w,h)
# assign instance avriables
@width, @height = w, h
@@count += 1
end
def self.printCount()
puts "Box count is : #@@count"
end
end
# create two object
box1 = Box.new(10, 20)
box2 = Box.new(30, 100)
# call class method to print box count
Box.printCount()
當(dāng)上面的代碼執(zhí)行時,它會產(chǎn)生以下結(jié)果:
to_s 方法:
所定義的任何類的實例應(yīng)該有一個 to_s 方法返回一個字符串形式表示對象。下面以一個簡單的例子來表示一個Box對象,在寬度和高度方面:
#!/usr/bin/ruby -w
class Box
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# define to_s method
def to_s
"(w:#@width,h:#@height)" # string formatting of the object.
end
end
# create an object
box = Box.new(10, 20)
# to_s method will be called in reference of string automatically.
puts "String representation of box is : #{box}"
當(dāng)上面的代碼執(zhí)行時,它會產(chǎn)生以下結(jié)果:
String representation of box is : (w:10,h:20)
訪問控制:
Ruby提供了三個級別的保護實例方法的級別:public, private 和 protected。 Ruby沒有應(yīng)用實例和類變量的任何訪問控制權(quán)。
- Public Methods: 任何人都可以被稱為public方法。方法默認(rèn)為公用初始化,這始終是 private 除外。 .
- Private Methods: private方法不能被訪問,或者甚至從類的外部瀏覽。只有類方法可以訪問私有成員。
- Protected Methods: 受保護的方法可以被調(diào)用,只能通過定義類及其子類的對象。訪問保存在類內(nèi)部。
以下是一個簡單的例子來說明三個訪問修飾符的語法:
#!/usr/bin/ruby -w
# define a class
class Box
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# instance method by default it is public
def getArea
getWidth() * getHeight
end
# define private accessor methods
def getWidth
@width
end
def getHeight
@height
end
# make them private
private :getWidth, :getHeight
# instance method to print area
def printArea
@area = getWidth() * getHeight
puts "Big box area is : #@area"
end
# make it protected
protected :printArea
end
# create an object
box = Box.new(10, 20)
# call instance methods
a = box.getArea()
puts "Area of the box is : #{a}"
# try to call protected or methods
box.printArea()
當(dāng)上面的代碼被執(zhí)行時,產(chǎn)生下面的結(jié)果。在這里,第一種方法被調(diào)用成功,但第二種方法給一個提示。
Area of the box is : 200
test.rb:42: protected method `printArea' called for #
Box:0xb7f11280 @height=20, @width=10> (NoMethodError)
類的繼承:
在面向?qū)ο蟮木幊讨凶钪匾母拍钪皇抢^承。繼承允許我們定義一個類在另一個類的項目,這使得它更容易創(chuàng)建和維護應(yīng)用程序。
繼承也提供了一個機會,重用代碼的功能和快速的實現(xiàn)時間,但不幸的是Ruby不支持多級的繼承,但Ruby支持混入。一個mixin繼承多重繼承,只有接口部分像一個專門的實現(xiàn)。
當(dāng)創(chuàng)建一個類,而不是寫入新的數(shù)據(jù)成員和成員函數(shù),程序員可以指定新的類繼承現(xiàn)有類的成員。這種現(xiàn)有的類稱為基類或父類和新類稱為派生類或子類。
Ruby也支持繼承。繼承和下面的例子解釋了這個概念。擴展類的語法很簡單。只需添加一個字符的超類聲明的名稱。例如,定義Box類的子類classBigBox:
#!/usr/bin/ruby -w
# define a class
class Box
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# instance method
def getArea
@width * @height
end
end
# define a subclass
class BigBox Box
# add a new instance method
def printArea
@area = @width * @height
puts "Big box area is : #@area"
end
end
# create an object
box = BigBox.new(10, 20)
# print the area
box.printArea()
當(dāng)上面的代碼執(zhí)行時,它會產(chǎn)生以下結(jié)果:
方法重載:
雖然可以在派生類中添加新的函數(shù),但有時想改變的行為已經(jīng)在父類中定義的方法。只需通過保持相同的方法名和重寫該方法的功能,如下圖所示,在這個例子可以這樣做:
#!/usr/bin/ruby -w
# define a class
class Box
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# instance method
def getArea
@width * @height
end
end
# define a subclass
class BigBox Box
# change existing getArea method as follows
def getArea
@area = @width * @height
puts "Big box area is : #@area"
end
end
# create an object
box = BigBox.new(10, 20)
# print the area using overriden method.
box.getArea()
運算符重載:
我們想“+”運算符使用+,*操作由一個標(biāo)量乘以一箱的寬度和高度,這里是一個版Box類的定義及數(shù)學(xué)運算符:
class Box
def initialize(w,h) # Initialize the width and height
@width,@height = w, h
end
def +(other) # Define + to do vector addition
Box.new(@width + other.width, @height + other.height)
end
def -@ # Define unary minus to negate width and height
Box.new(-@width, -@height)
end
def *(scalar) # To perform scalar multiplication
Box.new(@width*scalar, @height*scalar)
end
end
凍結(jié)對象:
有時候,我們要防止被改變的對象。凍結(jié)對象的方法可以讓我們做到這一點,有效地把一個對象到一個恒定。任何對象都可以被凍結(jié)通過調(diào)用Object.freeze。不得修改凍結(jié)對象:不能改變它的實例變量。
可以使用Object.frozen?語句檢查一個給定的對象是否已經(jīng)被凍結(jié),被凍結(jié)的情況下的對象語句方法返回true,否則返回false值。下面的示例 freeze 的概念:
#!/usr/bin/ruby -w
# define a class
class Box
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# accessor methods
def getWidth
@width
end
def getHeight
@height
end
# setter methods
def setWidth=(value)
@width = value
end
def setHeight=(value)
@height = value
end
end
# create an object
box = Box.new(10, 20)
# let us freez this object
box.freeze
if( box.frozen? )
puts "Box object is frozen object"
else
puts "Box object is normal object"
end
# now try using setter methods
box.setWidth = 30
box.setHeight = 50
# use accessor methods
x = box.getWidth()
y = box.getHeight()
puts "Width of the box is : #{x}"
puts "Height of the box is : #{y}"
當(dāng)上面的代碼執(zhí)行時,它會產(chǎn)生以下結(jié)果:
Box object is frozen object
test.rb:20:in `setWidth=': can't modify frozen object (TypeError)
from test.rb:39
類常量:
可以在類里定義分配一個直接的數(shù)字或字符串值,而不使用其定義一個變量為@@ 或 @。按照規(guī)范,我們保持常量名大寫。
一個常量一旦被定義就不能改變它的值,但可以在類里像常量一樣直接訪問,但如果要訪問一個類之外的常量,那么要使用類名::常量,所示在下面的例子。
#!/usr/bin/ruby -w
# define a class
class Box
BOX_COMPANY = "TATA Inc"
BOXWEIGHT = 10
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# instance method
def getArea
@width * @height
end
end
# create an object
box = Box.new(10, 20)
# call instance methods
a = box.getArea()
puts "Area of the box is : #{a}"
puts Box::BOX_COMPANY
puts "Box weight is: #{Box::BOXWEIGHT}"
當(dāng)上面的代碼執(zhí)行時,它會產(chǎn)生以下結(jié)果:
Area of the box is : 200
TATA Inc
Box weight is: 10
類常量繼承和實例方法一樣,可以覆蓋。
創(chuàng)建對象使用分配:
當(dāng)創(chuàng)建一個對象,而不調(diào)用它的構(gòu)造函數(shù)初始化,即可能有一個情況:采用 new 方法,在這種情況下可以調(diào)用分配,這將創(chuàng)造一個未初始化的對象,看下面的例子:
#!/usr/bin/ruby -w
# define a class
class Box
attr_accessor :width, :height
# constructor method
def initialize(w,h)
@width, @height = w, h
end
# instance method
def getArea
@width * @height
end
end
# create an object using new
box1 = Box.new(10, 20)
# create another object using allocate
box2 = Box.allocate
# call instance method using box1
a = box1.getArea()
puts "Area of the box is : #{a}"
# call instance method using box2
a = box2.getArea()
puts "Area of the box is : #{a}"
當(dāng)上面的代碼執(zhí)行時,它會產(chǎn)生以下結(jié)果:
Area of the box is : 200
test.rb:14: warning: instance variable @width not initialized
test.rb:14: warning: instance variable @height not initialized
test.rb:14:in `getArea': undefined method `*'
for nil:NilClass (NoMethodError) from test.rb:29
類信息:
如果類定義的可執(zhí)行代碼,這意味著他們在執(zhí)行的上下文中一些對象:自身都必須引用的東西。讓我們來看看它是什么。
#!/usr/bin/ruby -w
class Box
# print class information
puts "Type of self = #{self.type}"
puts "Name of self = #{self.name}"
end
當(dāng)上面的代碼執(zhí)行時,它會產(chǎn)生以下結(jié)果:
Type of self = Class
Name of self = Box
這意味著,一個類的定義,作為當(dāng)前對象的類并執(zhí)行。在元類和其超類的方法將在執(zhí)行過程中使用的方法定義。
您可能感興趣的文章:- 在Ruby中處理文件的輸入和輸出的教程
- 簡要說明Ruby中的迭代器
- 在Ruby中處理日期和時間的教程