English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Ruby базовый учебник

Ruby продвинутый учебник

Ориентированное на объекты программирование Ruby

Ruby является чистым объектно-ориентированным языком, в Ruby все представлено в виде объектов. Каждый объект в Ruby является объектом, даже самые базовые вещи: строки, числа, а также true и false, а также классы сами по себе также являютсяобъектомявляется Class Пример класса

Класс используется для определения формы объекта, он объединяет данные и методы, собирая их в упорядоченный пакет. Данные и методы в классе называются членами класса.

Определение класса Ruby

Когда вы определяете класс, вы фактически определяете план данных типа. Это не определяет данных, а определяет, что означает имя класса, то есть определяет, из чего состоят объекты класса, и какие операции можно выполнять на этих объектах.

Определение класса class начинается, за которым следуетимя классаи, наконец, с end для разделения и завершения определения класса. Например, мы используем ключевое слово class для определения класса Box, как показано ниже:

class Box
   код
end

По соглашению, имя должно начинаться с большой буквы, если оно содержит несколько слов, то каждое слово начинается с большой буквы, но между ними нет разделителей (например: CamelCase).

определение Ruby объекта

Класс предоставляет план объекта, поэтому, по сути, объекты создаются на основе класса. Мы используем является ключом для объявления класса объекта. Следующие строки объявляют два объекта класса Box: Ключевое слово new

box1 = Box.new
box2 = Box.new

initialize

initialize Метод constructor является стандартным классовым методом Ruby, это конструктор класса, и аналогичен методу initialize в других языках面向对象的 программирования constructor Метод initialize аналогичен по принципу работы. Когда вы хотите инициализировать一些 классовые переменные в момент создания объекта, этот метод оказывается полезен. Этот метод принимает множество параметров, как и другие методы Ruby, и при использовании этого метода перед ним необходимо放置 def как показано ниже:

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

переменные

переменныеявляются классовыми свойствами и становятся свойствами объекта при создании объекта класса. Свойства каждого объекта задаются отдельно и не делятся значениями с другими объектами. Внутри класса к этим свойствам обращаются с помощью оператора @, а снаружи класса используется ключевое словометоды доступаПубличныеМетод доступа. Ниже мы рассмотрим класс Box Для примера, let's take @width и @height as example variables for the class Box.

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

Методы доступа (getter) и установки (setter)

Чтобы читать переменные, определённые в классе снаружи класса, мы можем определить методы доступа (getter) для доступа. Следующий пример демонстрирует использование методов доступа:

Онлайн пример

#!/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 "盒子宽度 : #{x}"
puts "盒子高度 : #{y}"

Когда上面的 код выполняется, он создает следующие результаты:

盒子宽度 : 10
盒子高度 : 20

与用于访问变量值的访问器方法类似,Ruby 提供了一种在类的外部将参数传入类中已定义的变量,也就是所谓的设置器方法,定义如下:

Онлайн пример

#!/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 "盒子宽度 : #{x}"
puts "盒子高度 : #{y}"

Когда上面的 код выполняется, он создает следующие результаты:

盒子宽度 : 30
盒子高度 : 50

由于两种方法非常常用,Ruby 定义了 attr_accessor :variable_name、attr_reader :variable_name、attr_writer :variable_name 三种属性声明方法。其中:accessor=reader+writer.

同时注意:变量名前一定要带 : ,变量名之间要用 ,  分割。

示例方法

示例方法的定义与其他方法的定义一样,都是使用 def 关键字,但它们只能通过类示例来使用,如下面示例所示。它们的功能不限于访问示例变量,也能按照您的需求做更多其他的任务。

Онлайн пример

#!/usr/bin/ruby -w
 
# 定义类
class Box
   # 构造方法
   def initialize(w,h)
      @width, @height = w, h
   end
   # 示例方法
   def getArea
      @width * @height
   end
end
 
# 创建对象
box = Box.new(10, 20)
 
# 调用示例方法
a = box.getArea()
puts "盒子的面积是: #{a}"

Когда上面的 код выполняется, он создает следующие результаты:

盒子的面积是: 200

类方法 & 类变量

类变量是在类的所有示例中共享的变量。换句话说,类变量的示例可以被所有的对象示例访问。类变量以两个 @ 字符(@@)作为前缀,类变量必须在类定义中被初始化,如下面示例所示。

类方法使用 def self.methodname() 定义,类方法以 end 分隔符结尾。类方法可使用带有类名称的 classname.methodname 形式调用,如下面示例所示:

Онлайн пример

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

Когда上面的 код выполняется, он создает следующие результаты:

Box count is : 2

to_s 方法

您定义的任何类都有一个 to_s 示例方法来返回对象的字符串表示形式。下面是一个简单的示例,根据 width 和 height 表示 Box 对象:

Онлайн пример

#!/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 "Строка представления коробки: #{box}"

Когда上面的 код выполняется, он создает следующие результаты:

Строка представления коробки: (w:10,h:20)

Уровни доступа

Ruby предоставляет вам три уровня защиты методов примера,分别是 public, private или protectedRuby не применяет никакие уровни доступа к примерам и переменным класса.

  • Публичные методы: Публичные методы могут быть вызваны любыми объектами. По умолчанию все методы public, кроме метода initialize, который всегда private.

  • Приватные методы: Приватные методы не могут быть доступны или видны извне класса. Только методы класса могут доступ к приватным членам.

  • Защищенные методы: Защищенные методы могут быть вызваны только объектами класса и его подклассов. Доступ также возможен только в классе и его подклассах.

Вот простой пример, который демонстрирует синтаксис этих трех модификаторов:

Онлайн пример

#!/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 "Площадь большого ящика: #@area"
   end
   # Сделать метод примером защищенного
   protected :printArea
end
 
# 创建对象
box = Box.new(10, 20)
 
# 调用示例方法
a = box.getArea()
puts "盒子的面积是: #{a}"
 
# Пример вызова защищенного метода
box.printArea()

Когда этот код выполняется, он会产生以下结果. Здесь, первый метод был вызван успешно, но второй метод вызывает проблему.

盒子的面积是: 200
test.rb:42: protected method `printArea' called for #
<Box:0xb7f11280 @height=20, @width=10> (NoMethodError)

Наследование класса

Наследование — это один из важнейших концепций объектно-ориентированного программирования. Наследование позволяет нам определять класс на основе другого класса, что упрощает создание и поддержку приложений.

Наследование помогает повторно использовать код и быстро выполнять задачи, но к сожалению, Ruby не поддерживает множественное наследование, но Ruby поддерживает mixinsmixin по сути является специфической реализацией множественного наследования, в котором только интерфейсная часть может быть наследована.

Когда создается класс, программист может напрямую指定, что новый класс наследует члены существующего класса, что позволяет не начинать всё с нуля и создавать новые данные и функции. Этот существующий класс называетсябазовый класс или родительский класс, новый класс называетсяпроизводный класс или подкласс.

Ruby также предоставляет концепцию субклассификации, которая является наследованием. Следующий пример объясняет это понятие. Синтаксис расширения класса очень прост. Достаточно добавить символ < и имя родительского класса в строку класса. Например, следующий класс определён как: BigBox является 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 "Площадь большого ящика: #@area"
   end
end
 
# 创建对象
box = BigBox.new(10, 20)
 
# Вывод площади
box.printArea()

Когда上面的 код выполняется, он создает следующие результаты:

Площадь большого ящика: 200

Перегрузка методов

Хотя вы можете добавить новые функции в производный класс, иногда вы можете wanting изменить поведение методов, уже определённых в родительском классе. В этом случае вы можете оставить имя метода без изменений и перегрузить его функциональность, как показано в следующем примере:

Онлайн пример

#!/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 "Площадь большого ящика: #@area"
   end
end
 
# 创建对象
box = BigBox.new(10, 20)
 
# Вывод面积的 перегруженным методом
box.getArea()

Результат выполнения примера выше:

Площадь большого ящика: 200

Перегрузка операторов

Мы хотим использовать оператор + для выполнения векторной арифметики двух объектов Box, использовать оператор * для умножения width и height Box, использовать унарный оператор - для наложения обратного значения на width и height Box. Вот версия класса Box с определением математических операторов:

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

Замороженный объект

Sometimes, we want to prevent an object from being changed. In Object, the freeze method can achieve this, effectively turning an object into a constant. Any object can be made constant by calling Object.freeze to freeze. A frozen object cannot be modified, which means you cannot change its instance variables.

You can use Object.frozen? The method checks whether a given object has been frozen. If the object has been frozen, this method will return true, otherwise it will return a false value. The following example explains this 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}"

Когда上面的 код выполняется, он создает следующие результаты:

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

Class constant

You can define a constant within the class by assigning a direct numeric or string value to a variable. The definition of a constant does not require the use of @ or @@. By convention, the names of constants are written in uppercase.

Once a constant is defined, you cannot change its value. You can access the constant directly within the class, just like a variable, but if you want to access the constant outside the class, you must use classname::constant,如下面示例所示。

Онлайн пример

#!/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 "盒子的面积是: #{a}"
puts Box::BOX_COMPANY
puts "Box的重量是: #{Box::BOXWEIGHT}"

Когда上面的 код выполняется, он создает следующие результаты:

盒子的面积是: 200
TATA Inc
Box的重量是: 10

类常量可被继承,也可像示例方法一样被重载。

使用 allocate 创建对象

可能有一种情况,您想要在不调用对象构造器的情况下创建对象 initialize 在这种情况下创建对象,即,使用 new 方法创建对象,在这种情况下,您可以调用 allocate 来创建一个未初始化的对象,如下面示例所示:

Онлайн пример

#!/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 "盒子的面积是: #{a}"
 
# 使用 box2 调用示例方法
a = box2.getArea()
puts "盒子的面积是: #{a}"

Когда上面的 код выполняется, он создает следующие результаты:

盒子的面积是: 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

类信息

Ruby的自我(self)和Java的this有相似之处,但又大不相同。Java的方法都是在示例方法中引用,所以this通常指向当前对象。而Ruby的代码逐行执行,所以在不同的上下文(context)中self就有了不同的含义。让我们来看看下面的示例:。

Онлайн пример

#!/usr/bin/ruby -w
 
class Box
   # Вывод информации о классе
   puts "Class of self = #{self.class}"
   puts "Name of self = #{self.name}"
end

Когда上面的 код выполняется, он создает следующие результаты:

Класс self = Class
Имя self = Box

Это означает, что определение класса можно выполнить, выполнив этот класс как текущий объект, и это также означает, что метод в метаклассе и родительском классе доступен в процессе выполнения метода определения.