Ruby 是纯粹面向对象的语言。Ruby将每一个事物都看做对象,甚至原始的类型,字符串,数值, true/false. ruby
本节介绍与面向对象有关的主要功能。ide
类是来指定对象的形式,包含数据和方法。类内的数据和方法,被称做成员。this
定义类的时候,定义类的蓝本,即类对象包含什么已经能够对对象作什么操做。scala
关键词 class开头, 跟着类名 class name, 最后以 end结束. code
class Box code end 类名必须以大写字母开头。习惯上用驼峰式命名(CamelCase).
建立新的对象,用关键词neworm
box1 = Box.new box2 = Box.new
initialize method 初始化方法 是标准类方法,和其它面向对象的语言的构造器constructor 相似。初始化方法能够在对象建立时初始化类变量。 对象
class Box def initialize(w,h) @width, @height = w, h end end
instance variables 实例变量是类属性,当用类来建立对象时变成对象特性。每一个对象的属性单独赋值,各个对象不共享。类内用@访问,类外用公共方法accessor 访问。 继承
class Box def initialize(w,h) # assign instance variables @width, @height = w, h end end
要在类外访问类变量,必须在accessor methods内定义。,accessor method 又 叫 getter methods.教程
demo_accessor.rbip
# 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
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
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
每一个类应该定义一个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)
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
面向对象的最重要概念就是继承。继承能够用其它类定义新的类,便于建立和维护应用。
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
你能够在派生类添加新的功能,但有时候想修改父类定义的方法。你能够保持一样的方法名,从新定义方法,这称做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()
将操做符从新定义,叫作操做符重载。如下就是定义盒子+,-,* 操做符重载的例子。
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
有时候,不想一个对象被改变。对象的冻结方法容许如此作,将对象变成一个常量。任何对象能够调用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)
类常量。你能够在类内定义常量并赋值,而不用@或@@。常量习惯用大写字母。
在类外访问常量方式 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 类常量能够继承,也能够像实例方法同样被重写。
建立一个对象不调用它的构造器 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)
若是一个类是可执行代码,这暗示它们在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