Ruby 簡明教程 高級進階 Part 1

Ruby 簡明教程

高級進階

 

1. Ruby - Object Oriented 面向對象

 

Ruby 是純粹面向對象的語言。Ruby將每個事物都看作對象,甚至原始的類型,字符串,數值, true/false. 

本節介紹與面向對象有關的主要功能。

類是來指定對象的形式,包含數據和方法。類內的數據和方法,被稱作成員。

1.1Ruby Class Definition

定義類的時候,定義類的藍本,即類對象包含什麼已經可以對對象做什麼操作。

關鍵詞 class開頭, 跟着類名 class name,  最後以 end結束

class Box
   code
end

類名必須以大寫字母開頭。習慣上用駝峯式命名(CamelCase).

1.2 Define Ruby Objects

創建新的對象,用關鍵詞new

box1 = Box.new
box2 = Box.new

1.3 The initialize Method

 initialize method 初始化方法  是標準類方法,和其它面向對象的語言的構造器constructor 類似。初始化方法可以在對象創建時初始化類變量。 

class Box
   def initialize(w,h)
      @width, @height = w, h
   end
end

1.4 The instance Variables

 instance variables 實例變量是類屬性,當用類來創建對象時變成對象特性。每個對象的屬性單獨賦值,各個對象不共享。類內用@訪問,類外用公共方法accessor 訪問。  

class Box
   def initialize(w,h)
      # assign instance variables
      @width, @height = w, h
   end
end

1.5 The accessor & setter Methods

要在類外訪問類變量,必須在accessor methods內定義。,accessor method 又 叫 getter methods.

demo_accessor.rb

# 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}"

執行結果:

zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_accessor.rb
Width of the box is : 10
Height of the box is : 20

同 accessor methods類似,從類外部設置類變量,使用setter methods

 

# 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}"

執行結果

zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_setter.rb
Width of the box is : 30
Height of the box is : 50

1.6 The instance Methods

 instance methods 實例方法和其它方法一樣用def 定義,可以使用類實例。 

 

# 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}"

結果:

zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_instancemethod.rb
Area of the box is : 200

1.7 The class Methods and Variables

 class variables 類變量,是在類實例中共享。 也就是說一個變量實例,被對象實例訪問。 類變量以倆個@@開頭。必須在類定義時初始化。. 

class method類方法用 def self.methodname()  來定義,以end 結束。用 類名.方法名 classname.methodname 來訪問。

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

運行結果:

zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_classmethodVar.rb
Box count is : 2

1.8 The to_s Method

每個類應該定義一個to_s 實例方法,返回代表對象的字符串。

 

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

運行結果:

zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_tostring.rb
String representation of box is : (w:10,h:20)

1.9 Access Control

Ruby 提供了三種對實例方法的保護 public, private, or protected. Ruby 對類變量和實例的訪問沒有控制。

  • Public Methods −  公共方法,都可以訪問。除了初始化方法默認是private,其它默認是公共的。

  • Private Methods − 私有方法不能從類外部訪問,查看。只有類方法可以訪問私有方法。.

  • Protected Methods − 保護方法不能被外部調用,只有被定義的類及其子類的對象調用。

 

 

# 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
   def ex_printArea
       self.printArea()
   end

end

# create an object
box = Box.new(10, 20)

# call instance methods
a = box.getArea()
puts "Area of the box is : #{a}"

box.ex_printArea()

# try to call protected methods
box.printArea()


 第一個第二個方法成功,第三個方法出錯。保護的不能直接調用,但是在可以在類內被self調用。

zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_rubyAccessControl.rb
Area of the box is : 200
Big box area is : 200
Traceback (most recent call last):
demo_rubyAccessControl.rb:48:in `<main>': protected method `printArea' called for #<Box:0x0000556a4ab600d0 @width=10, @height=20, @area=200> (NoMethodError)
Did you mean?  printArea
               ex_printArea

1.10 Class Inheritance 類繼承

面向對象的最重要概念就是繼承。繼承可以用其它類定義新的類,便於創建和維護應用。

Inheritance also provides an opportunity to reuse the code functionality and fast implementation time but unfortunately Ruby does not support multiple levels of inheritances but Ruby supports mixins. A mixin is like a specialized implementation of multiple inheritance in which only the interface portion is inherited.

繼承可以代碼複用,加速開發。不過Ruby 不支持多重繼承,但是提供了混合機制mixins. 混合像多重繼承的一個特殊實現,只有界面interface被繼承。

以存在的類稱作基類或超類base class or superclass,新建的類叫派生類或子類 derived class or sub-class.

Ruby支持子類概念,即繼承。在子類名字後加<基類名。

下面例子定義BigBox 作爲 Box 的子類

 

# 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()

結果

zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_inheritbox.rb
Big box area is : 200

1.11 Methods Overriding

你可以在派生類添加新的功能,但有時候想修改父類定義的方法。你可以保持同樣的方法名,重新定義方法,這稱作c重寫overriding . 

demo_overriding.rb

# 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()

1.12 Operator Overloading

將操作符重新定義,叫做操作符重載。以下就是定義盒子+,-,* 操作符重載的例子。

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

1.13 Freezing Objects 凍結對象

有時候,不想一個對象被改變。對象的凍結方法允許如此做,將對象變成一個常量。任何對象可以調用Object.freeze來凍結。. 被凍結的對象不能改變。

使用Object.frozen? 來檢查對象是否被凍結。

demo_freeze.rb

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

# before object is frozen
# use accessor methods 
x = box.getWidth() 
y = box.getHeight() 
puts "Width of the box is : #{x}" 
puts "Height of the box is : #{y}"

# 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}"

執行結果:

zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_freeze.rb
Width of the box is : 10
Height of the box is : 20
Box object is frozen object
Traceback (most recent call last):
    1: from demo_freeze.rb:45:in `<main>'
demo_freeze.rb:18:in `setWidth=': can't modify frozen Box (FrozenError)

1.14 Class Constants

類常量。你可以在類內定義常量並賦值,而不用@或@@。常量習慣用大寫字母。

在類外訪問常量方式 classname::constant a

demo_constant.rb

# 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}"

執行結果

Area of the box is : 200
TATA Inc
Box weight is: 10

類常量可以繼承,也可以像實例方法一樣被重寫。

1.15 Create Object Using Allocate

創建一個對象不調用它的構造器 initialize ,即new 方法,可以使用 allocate

demo_allocate.rb

# 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}"

執行結果

zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_allocate.rb
Area of the box is : 200
Traceback (most recent call last):
    1: from demo_allocate.rb:27:in `<main>'
demo_allocate.rb:12:in `getArea': undefined method `*' for nil:NilClass (NoMethodError)
 

1.15 Class Information

 如果一個類是可執行代碼,這暗示它們在some個對象的context 中執行。

下例返回類的類型和名字。

class Box
   # print class information
   puts "Type of self = #{self.type}"
   puts "Name of self = #{self.name}"
end

結果

Type of self = Class
Name of self = Box

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章