Ruby orienté objet


Ruby est un langage purement orienté objet, et tout dans Ruby apparaît sous forme d'objets. Chaque valeur dans Ruby est un objet, même les choses les plus primitives : les chaînes, les nombres, même vrais et faux, sont des objets. La classe elle-même est également un Object, qui est une instance de la classe Class. Ce chapitre vous apprendra toutes les principales fonctionnalités liées à Ruby orienté objet. La classe

est utilisée pour spécifier la forme d'un objet, qui combine la représentation des données et des méthodes pour organiser les données dans un package soigné. Les données et méthodes d’une classe sont appelées membres de la classe.

Définition de classe Ruby

Lorsque vous définissez une classe, vous définissez en fait un modèle d'un type de données. Cela ne définit en réalité aucune donnée, mais définit plutôt ce que signifie le nom de la classe, c'est-à-dire en quoi consistera un objet de la classe et quelles opérations peuvent être effectuées sur l'objet.

La définition de la classe commence par le mot-clé class, suivi du nom de la classe, et enfin séparé par une fin pour terminer la définition de la classe . Par exemple, nous utilisons la classe mot-clé pour définir la classe Box comme suit :

class Box
   code
end

Par convention, le nom doit commencer par une majuscule. S'il contient plusieurs mots, la première lettre de chaque mot est en majuscule, mais il n'y a pas de séparation entre eux (par exemple : CamelCase).

Définition des objets Ruby

Les classes fournissent le modèle des objets, donc fondamentalement, les objets sont créés en fonction des classes. Nous déclarons les objets d'une classe en utilisant le mot-clé new. L'instruction suivante déclare deux objets de la classe Box :

box1 = Box.new
box2 = Box.new

méthode initialize

initialize est une méthode de classe Ruby standard, qui est le constructeur de la classe, et constructeur dans d'autres langages de programmation orientés objet fonctionne de la même manière. La méthode initialize est pratique lorsque vous souhaitez initialiser certaines variables de classe lors de la création d'un objet. Cette méthode prend une série de paramètres. Comme les autres méthodes Ruby, lorsque vous utilisez cette méthode, vous devez placer le mot-clé def devant, comme suit :

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

Variable d'instance

<🎜. >

Les variables d'instance sont des attributs de classe, et elles deviennent des attributs de l'objet lors de l'utilisation de la classe pour créer un objet. Les propriétés de chaque objet sont attribuées individuellement et ne partagent pas de valeurs avec d'autres objets. À l'intérieur de la classe, ces propriétés sont accessibles à l'aide de l'opérateur @, et en dehors de la classe, elles sont accessibles à l'aide des méthodes publiques appelées Méthodes d'accès. Ci-dessous, nous prenons la classe Box définie ci-dessus comme instance et utilisons @width et @height comme variables d'instance de la classe Box.

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

Méthodes Accessor & Setter

Afin d'utiliser des variables en dehors de la classe, nous devons définir ces variables à l'intérieur de la

Méthode Accessor, accessor est en fait équivalent à getter. L'exemple suivant montre l'utilisation de la méthode d'accesseur :

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


Lorsque le code ci-dessus est exécuté, il produit le résultat suivant :

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

est le même tels qu'utilisés pour les méthodes Accessor pour accéder aux valeurs des variables, Ruby fournit un moyen de définir des valeurs de variable en dehors de la classe, ce qu'on appelle la

méthode setter, qui est définie comme suit :

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


Lorsque le code ci-dessus est exécuté, il produit les résultats suivants :

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

Méthode d'instance

La définition de la méthode d'instance est la même que la définition des autres méthodes, en utilisant le mot-clé def, mais elles ne sont accessibles que via des instances de classe Utiliser, comme le montre l'exemple ci-dessous. Leur fonctionnalité ne se limite pas à accéder aux variables d'instance, mais peut également effectuer de nombreuses autres tâches selon vos besoins.

#!/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 "Area of the box is : #{a}"


Lorsque le code ci-dessus est exécuté, il produira les résultats suivants :

Area of the box is : 200

Méthodes de classe et variables de classe

Les variables de classe sont des variables partagées entre toutes les instances d'une classe. En d’autres termes, les instances de variables de classe sont accessibles par toutes les instances d’objet. Les variables de classe sont préfixées par deux caractères @ (@@) et doivent être initialisées dans la définition de classe, comme indiqué dans l'exemple suivant. La

La méthode de classe est définie à l'aide de def self.methodname(). Les méthodes de classe peuvent être appelées en utilisant la forme classname.methodname avec le nom de la classe, comme indiqué dans l'exemple suivant :

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


Lorsque le code ci-dessus est exécuté, il produit le résultat suivant :

Box count is : 2

méthode to_s

Toute classe que vous définissez a une méthode d'instance to_s qui renvoie une représentation sous forme de chaîne d'un objet. Voici un exemple simple qui représente un objet Box en termes de largeur et de hauteur :

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


Lorsque le code ci-dessus est exécuté, il produira les résultats suivants :

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

Contrôle d'accès

Ruby vous offre trois niveaux de protection des méthodes d'instance, qui sont public, privé ou protégé. Ruby n'applique aucun contrôle d'accès sur les variables d'instance et de classe.

  • Méthode publique : La méthode publique peut être appelée par n'importe quel objet. Par défaut, les méthodes sont toutes publiques, à l'exception de la méthode initialize qui est toujours privée.

  • Méthodes privées : Les méthodes privées ne sont pas accessibles ni visibles depuis l'extérieur de la classe. Seules les méthodes de classe peuvent accéder aux membres privés.

  • Méthode protégée : La méthode protégée ne peut être appelée que par les objets de la classe et ses sous-classes. L'accès n'est également possible qu'au sein de la classe et de ses sous-classes.

Ce qui suit est un exemple simple démontrant la syntaxe de ces trois modificateurs :

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


Lorsque le code ci-dessus est exécuté, il produit les résultats suivants. Ici, le premier appel de méthode réussit, mais la deuxième méthode crée un problème.

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

Héritage de classe

L'héritage est l'un des concepts les plus importants de la programmation orientée objet. L'héritage nous permet de définir une classe basée sur une autre classe, ce qui facilite la création et la maintenance d'applications.

L'héritage aide à la réutilisation du code et à une exécution rapide, malheureusement Ruby ne prend pas en charge l'héritage multiple, mais Ruby prend en charge les mixins. Un mixin est comme une implémentation spécifique de l'héritage multiple, où seule la partie interface est héritable.

Lors de la création d'une classe, les programmeurs peuvent spécifier directement que la nouvelle classe hérite des membres d'une classe existante, il n'est donc pas nécessaire d'écrire de nouvelles données membres et fonctions membres à partir de zéro. Cette classe existante est appelée une classe de base ou classe parent, et la nouvelle classe est appelée une classe ou sous-classe dérivée.

Ruby fournit également le concept de sous-classement, qui est l'héritage. L'exemple suivant explique ce concept. La syntaxe pour étendre une classe est très simple. Ajoutez simplement un caractère < et le nom de la classe parent à l'instruction de classe. Par exemple, ce qui suit définit la classe BigBox qui est une sous-classe de 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()


Lorsque le code ci-dessus est exécuté , cela produira le résultat suivant :

Big box area is : 200

Surcharge de méthode

Bien que vous puissiez ajouter de nouvelles fonctionnalités dans une classe dérivée, vous souhaiterez parfois modifier le comportement d'une méthode déjà définie dans la classe parent. À ce stade, vous pouvez conserver le nom de la méthode inchangé et surcharger la fonction de la méthode, comme indiqué dans l'exemple suivant :

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


Le résultat de sortie de l'exemple ci-dessus est :

Big box area is : 200

Surcharge d'opérateur

Nous voulons utiliser l'opérateur + pour effectuer l'addition vectorielle de deux objets Box, utiliser l'opérateur * pour multiplier la largeur et la hauteur de la Box, et utiliser l'unaire opérateur - pour la largeur de la boîte négative de la hauteur. Voici une version de la classe Box avec des définitions d'opérateurs mathématiques :

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

Gelage d'objets

Parfois, nous souhaitons empêcher la modification d'un objet. Dans Object, cela est accompli avec la méthode freeze, qui transforme efficacement un objet en constante. N'importe quel objet peut être gelé en appelant Object.freeze. Un objet figé ne peut pas être modifié, c'est-à-dire que vous ne pouvez pas modifier ses variables d'instance.

Vous pouvez vérifier si un objet donné a été gelé en utilisant la méthode Object.frozen?. Cette méthode renvoie vrai si l'objet a été gelé, sinon elle renvoie une valeur fausse. L'exemple suivant explique ce 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}"


Lorsque le code ci-dessus est exécuté, il produira le résultat suivant :

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

Class Constant

Vous pouvez définir une constante à l'intérieur d'une classe en attribuant une valeur numérique ou chaîne directe à une variable. La définition d'une constante ne nécessite pas l'utilisation de @ ou @@. Par convention, les noms de constantes sont en majuscules.

Une fois qu'une constante est définie, vous ne pouvez pas modifier sa valeur. Vous pouvez accéder à la constante directement à l'intérieur de la classe, tout comme une variable, mais si vous souhaitez accéder à la constante en dehors de la classe, vous devez utiliser <🎜. >classname::constant, comme le montre l'exemple ci-dessous.

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


Lorsque le code ci-dessus est exécuté, il produira les résultats suivants :

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

Les constantes de classe peuvent être héritées et peuvent également être remplacées comme les méthodes d'instance charger.

Création d'objets à l'aide d'allocate

Il peut y avoir une situation où vous souhaitez créer un objet sans appeler le constructeur d'objet

initialize, c'est-à-dire créer un objet en utilisant la nouvelle méthode , auquel cas vous pouvez appeler allocate pour créer un objet non initialisé, comme indiqué dans l'exemple suivant :

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


Lorsque le code ci-dessus s'exécute, il produit le résultat suivant :

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

Informations de classe

Ruby et Java ont des similitudes, mais ils sont également très différents. Les méthodes Java sont référencées dans les méthodes d'instance, elles pointent donc généralement vers l'objet actuel. Le code de Ruby est exécuté ligne par ligne, donc self a des significations différentes selon les contextes. Jetons un coup d'œil à l'instance suivante : .

#!/usr/bin/ruby -w

class Box
   # 输出类信息
   puts "Class of self = #{self.class}"
   puts "Name of self = #{self.name}"
end


Lorsque le code ci-dessus est exécuté, il produira le résultat suivant :

Class of self = Class
Name of self = Box

Cela signifie que le classe La définition peut être exécutée en faisant de la classe l'objet actuel, ce qui signifie également que la méthode dans la métaclasse et la superclasse est disponible lors de l'exécution de la définition de la méthode.