Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Ruby object-oriented


May 12, 2021 Ruby


Table of contents


Ruby is object-oriented

Ruby is a pure object-oriented language, and everything in Ruby comes in the form of objects. E ach value in Ruby is an object, even the most primitive: strings, numbers, even true and false objects. T he class itself is also an object and is an instance of the Class class. This chapter will show you all the key object-oriented features associated with Ruby.

Class is used to specify the form of an object, which combines data notation and methods to organize the data into a neat package. The data and methods in the class are called members of the class.

Ruby class definition

When you define a class, you actually define a blueprint for a data type. This does not actually define any data, but rather what the name of the class means, that is, what makes up the object of the class and what can be done on that object.

The class definition starts with the keyword class, followed by the class name, and ends with an end separation to terminate the class definition. For example, we use the keyword class to define a Box class, as follows:

class Box
   code
end

By convention, names must begin with capital letters, and if they contain more than one word, each word is capital, but there is no separator (ex: CamelCase).

Define ruby objects

The class provides a blueprint for the object, so basically, the object is created based on the class. W e use the new keyword to declare the object of the class. The following statement declares two objects of the class Box:

box1 = Box.new
box2 = Box.new

The initialize method

The initialize approach is a standard Ruby class approach that works similarly to constructor in other object-oriented programming languages. W hen you want to initialize some class variables while creating an object, the initialize method comes in use. The method has a series of parameters that, like other Ruby methods, must be preceded by the def keyword, as follows:

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

The instance variable

Instance variables are class properties that become object properties when they are created with classes. T he properties of each object are assigned separately and do not share values with other objects. I nside the class, these properties are accessed using the operator, and outside the class, they are accessed using a common method called the Accessor method. Let's use the class Box defined above as an example, @width and @height as instance variables for the class Box.

class Box
   def initialize(w,h)
      # 给实例变量赋值
      @width, @height = w, h
   end
end

Accessor and Seter method

In order to use variables outside the class, we must define them inside the Accessor method, also known as the Geter method. The following example demonstrates the use of the accessor method:

#!/usr/bin/ruby -w

# 定义类
class Box
   # 构造器方法
   def initialize(w,h)
      @width, @height = w, h
   end

   # 访问器方法
   def printWidth
      @width
   end

   def printHeight
      @height
   end
end

# 创建对象
box = Box.new(10, 20)

# 使用访问器方法
x = box.printWidth()
y = box.printHeight()

puts "Width of the box is : #{x}"
puts "Height of the box is : #{y}"
Try it out . . .


When the code above executes, it produces the following results:

Width of the box is : 10
Height of the box is : 20

Similar to the accessor method used to access variable values, Ruby provides a way to set variable values outside the class, known as the Seter method, as defined as follows:

#!/usr/bin/ruby -w

# 定义类
class Box
   # 构造器方法
   def initialize(w,h)
      @width, @height = w, h
   end

   # 访问器方法
   def getWidth
      @width
   end
   def getHeight
      @height
   end

   # 设置器方法
   def setWidth=(value)
      @width = value
   end
   def setHeight=(value)
      @height = value
   end
end

# 创建对象
box = Box.new(10, 20)

# 使用设置器方法
box.setWidth = 30
box.setHeight = 50

# 使用访问器方法
x = box.getWidth()
y = box.getHeight()

puts "Width of the box is : #{x}"
puts "Height of the box is : #{y}"
Try it out . . .


When the code above executes, it produces the following results:

Width of the box is : 30
Height of the box is : 50

The instance method

The definition of an instance method, like the definition of other methods, uses the def keyword, but they can only be used through class instances, as shown in the following example. Their capabilities are not limited to accessing instance variables, but they can do more to meet your needs.

#!/usr/bin/ruby -w

# 定义类
class Box
   # constructor method
   def initialize(w,h)
      @width, @height = w, h
   end
   # 实例方法
   def getArea
      @width * @height
   end
end

# 创建对象
box = Box.new(10, 20)

# 调用实例方法
a = box.getArea()
puts "Area of the box is : #{a}"
Try it out . . .


When the code above executes, it produces the following results:

Area of the box is : 200

Class methods and class variables

A class variable is a variable that is shared in all instances of a class. I n other words, instances of class variables can be accessed by all object instances. The class variable is prefixed with two characters, and the class variable must be initialized in the class definition, as shown in the following example.

Class methods are defined using def self.methodname(), and class methods end with an end separator. Class methods can be called in the form of classname.methodname with the class name, as shown in the following example:

#!/usr/bin/ruby -w

class Box
   # 初始化类变量
   @@count = 0
   def initialize(w,h)
      # 给实例变量赋值
      @width, @height = w, h

      @@count += 1
   end

   def self.printCount()
      puts "Box count is : #@@count"
   end
end

# 创建两个对象
box1 = Box.new(10, 20)
box2 = Box.new(30, 100)

# 调用类方法来输出盒子计数
Box.printCount()
Try it out . . .


When the code above executes, it produces the following results:

Box count is : 2

to_s method

Any class you define has a to_s method to return a string representation of the object. Here's a simple example of a Box object based on width and height:

#!/usr/bin/ruby -w

class Box
   # 构造器方法
   def initialize(w,h)
      @width, @height = w, h
   end
   # 定义 to_s 方法
   def to_s
      "(w:#@width,h:#@height)"  # 对象的字符串格式
   end
end

# 创建对象
box = Box.new(10, 20)

# 自动调用 to_s 方法
puts "String representation of box is : #{box}"
Try it out . . .


When the code above executes, it produces the following results:

String representation of box is : (w:10,h:20)

Access control

Ruby gives you three levels of instance method protection: public, private, or protected. Ruby does not apply any access control on instances and class variables.

  • Public method: P ublic methods can be called by any object. By default, the methods are public, except that the initialize method is always private.
  • Private method: P rivate methods cannot be accessed or viewed from outside the class. Only class methods can access private members.
  • Protected method: T he Protected method can only be called by objects of classes and their sub-classes. Access can also only take place inside classes and their sub-classes.

Here is a simple example that demonstrates the syntax of these three modifiers:

#!/usr/bin/ruby -w

# 定义类
class Box
   # 构造器方法
   def initialize(w,h)
      @width, @height = w, h
   end

   # 实例方法默认是 public 的
   def getArea
      getWidth() * getHeight
   end

   # 定义 private 的访问器方法
   def getWidth
      @width
   end
   def getHeight
      @height
   end
   # make them private
   private :getWidth, :getHeight

   # 用于输出面积的实例方法
   def printArea
      @area = getWidth() * getHeight
      puts "Big box area is : #@area"
   end
   # 让实例方法是 protected 的
   protected :printArea
end

# 创建对象
box = Box.new(10, 20)

# 调用实例方法
a = box.getArea()
puts "Area of the box is : #{a}"

# 尝试调用 protected 的实例方法
box.printArea()
Try it out . . .


When the above code is executed, it produces the following results. Here, the first method is called successfully, but the second method creates a problem.

Area of the box is : 200
test.rb:42: protected method `printArea' called for #
<Box:0xb7f11280 @height=20, @width=10> (NoMethodError)

The inheritance of the class

Inheritance is one of the most important concepts in object-oriented programming. Inheritance allows us to define a class based on another class, which makes it easier to create and maintain applications.

Inheritance helps reuse code and execute quickly, and unfortunately Ruby doesn't support multi-inheritance, but Ruby supports mixins. Mixin is like a specific implementation of multiple inheritance, in which only the interface part is inheritable.

When creating a class, the programmer can specify directly that the new class inherits members from an existing class, so that no new data members and member functions are written from the beginning. This existing class is called a base class or parent class, and the new class is called a derived class or sub-class.

Ruby also provides the concept of sub-classification, which is inheritance, which is explained in the following example. E xtending the syntax of a class is very simple. J ust add the name of the character and the parent class to the class statement. For example, the following defines the class BigBox as a sub-class of Box:

#!/usr/bin/ruby -w

# 定义类
class Box
   # 构造器方法
   def initialize(w,h)
      @width, @height = w, h
   end
   # 实例方法
   def getArea
      @width * @height
   end
end

# 定义子类
class BigBox < Box

   # 添加一个新的实例方法
   def printArea
      @area = @width * @height
      puts "Big box area is : #@area"
   end
end

# 创建对象
box = BigBox.new(10, 20)

# 输出面积
box.printArea()

Try it out . . .


When the code above executes, it produces the following results:

Big box area is : 200

Method overload

Although you can add new functionality to a derived class, sometimes you may want to change the behavior of methods that are already defined in the parent class. At this point, you can keep the method name the same, and overload the functionality of the method, as shown in the following example:

#!/usr/bin/ruby -w

# 定义类
class Box
   # 构造器方法
   def initialize(w,h)
      @width, @height = w, h
   end
   # 实例方法
   def getArea
      @width * @height
   end
end

# 定义子类
class BigBox < Box

   # 改变已有的 getArea 方法
   def getArea
      @area = @width * @height
      puts "Big box area is : #@area"
   end
end

# 创建对象
box = BigBox.new(10, 20)

# 使用重载的方法输出面积
box.getArea()

Try it out . . .

The operator is overloaded

We want to do vector addition of two Box objects using the plus operator, multiply the width and height of the Box by the operator, and use the umnational operator - reverse the width and height of the Box. Here's a version of the Box class with a mathematical operator definition:

class Box
  def initialize(w,h) # 初始化 width 和 height
    @width,@height = w, h
  end

  def +(other)         # 定义 + 来执行向量加法
    Box.new(@width + other.width, @height + other.height)
  end

  def -@               # 定义一元运算符 - 来对 width 和 height 求反
    Box.new(-@width, -@height)
  end

  def *(scalar)        # 执行标量乘法
    Box.new(@width*scalar, @height*scalar)
  end
end

Freeze the object

Sometimes we want to prevent objects from being changed. I n Object, the freeze method does this by effectively turning an object into a constant. A ny object can be frozen by calling Object.freeze. Frozen objects cannot be modified, that is, you cannot change its instance variables.

You can use the Object.frozen? method to check whether a given object has been frozen. I f the object is frozen, the method returns true, otherwise a false value is returned. The following example explains the concept:

#!/usr/bin/ruby -w

# 定义类
class Box
   # 构造器方法
   def initialize(w,h)
      @width, @height = w, h
   end

   # 访问器方法
   def getWidth
      @width
   end
   def getHeight
      @height
   end

   # 设置器方法
   def setWidth=(value)
      @width = value
   end
   def setHeight=(value)
      @height = value
   end
end

# 创建对象
box = Box.new(10, 20)

# 让我们冻结该对象
box.freeze
if( box.frozen? )
   puts "Box object is frozen object"
else
   puts "Box object is normal object"
end

# 现在尝试使用设置器方法
box.setWidth = 30
box.setHeight = 50

# 使用访问器方法
x = box.getWidth()
y = box.getHeight()

puts "Width of the box is : #{x}"
puts "Height of the box is : #{y}"
Try it out . . .


When the code above executes, it produces the following results:

Box object is frozen object
test.rb:20:in `setWidth=': can't modify frozen object (TypeError)
        from test.rb:39

Class constant

You can define a constant inside a class by assigning a direct value or string value to a variable, and the definition of a constant does not require the use of . . . or . . By convention, the name of a constant is capitaled.

Once a constant is defined, you cannot change its value, and you can access the constant directly inside the class, just as you would a variable, but if you want to access the constant outside the class, you must use classname::constant, as shown in the following example.

#!/usr/bin/ruby -w

# 定义类
class Box
   BOX_COMPANY = "TATA Inc"
   BOXWEIGHT = 10
   # 构造器方法
   def initialize(w,h)
      @width, @height = w, h
   end
   # 实例方法
   def getArea
      @width * @height
   end
end

# 创建对象
box = Box.new(10, 20)

# 调用实例方法
a = box.getArea()
puts "Area of the box is : #{a}"
puts Box::BOX_COMPANY
puts "Box weight is: #{Box::BOXWEIGHT}"
Try it out . . .


When the code above executes, it produces the following results:

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

Class constants can be inherited or overloaded like instance methods.

Create an object using allocate

There may be a situation where you want to create an object without calling the object constructor initialize, that is, creating an object using the new method, in which case you can call allocate to create an un initialized object, as shown in the following example:

#!/usr/bin/ruby -w

# 定义类
class Box
   attr_accessor :width, :height

   # 构造器方法
   def initialize(w,h)
      @width, @height = w, h
   end

   # 实例方法
   def getArea
      @width * @height
   end
end

# 使用 new 创建对象
box1 = Box.new(10, 20)

# 使用 allocate 创建两一个对象
box2 = Box.allocate

# 使用 box1 调用实例方法
a = box1.getArea()
puts "Area of the box is : #{a}"

# 使用 box2 调用实例方法
a = box2.getArea()
puts "Area of the box is : #{a}"
Try it out . . .


When the code above executes, it produces the following results:

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

Class information

If class definitions are executable code, which means that they can be executed in the context of an object, self must reference something. Let's take a look at the following example: .

#!/usr/bin/ruby -w

class Box
   # 输出类信息
   puts "Type of self = #{self.type}"
   puts "Name of self = #{self.name}"
end
Try it out . . .


When the code above executes, it produces the following results:

Type of self = Class
Name of self = Box

This means that the class definition can be executed by treating the class as the current object, and it also means that the method in the meta-class and the parent class is available during the method definition execution.