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

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值