Le langage Ruby

  1. Introduction
  2. Variables et constantes
  3. Symbôles et chaînes de caractères
    1. Les symbôles
    2. Les chaînes de caractères
  4. Méthodes
    1. Les appels de méthode
    2. Analyse syntaxique du langage Ruby
    3. Les listes de variables d'entrées
    4. Les blocs de code
    5. Les appels de méthode avec bloc de code
    6. Les méthodes send, respond_to?(x), method_missing(x)
    7. La définition d'une méthode singleton
  5. L'object main
  6. Le mot clé self
  7. Variables d'instance et variables de classe
  8. Classes
    1. Méthodes d'instance
    2. Variables d'instance et variable de classe
    3. La méthode d'instance initialize
    4. Les méthodes d'instances d'écriture et de lecture d'attribut
    5. Les méthodes de la famille attr_*
    6. Les méthodes de classe
    7. Les constantes et le connecteur ::
    8. La hierarchie des classes
    9. Les modules
  9. Le mot clé self et les contextes
  10. Variables globales prédéfinies
  11. Règles d'accès aux méthodes
    1. Les méthodes de niveau supérieur
  12. Classe singleton ou Metaclasses
  13. Conditions, boucles et itérateurs
  14. Constructeurs littéraux

  15. Les méthodes Kernel::eval et Object#instance_eval et Module#class_eval et Module#define_method
  16. les objects invocables (callable object)
    1. Les Proc et les lambda
    2. Le préfixe &
    3. Les méthodes sont des objects
  17. Aspects de construction
    1. Méthode Module#included
    2. Méthode Class#inherited
    3. Méthode Module#const_missing
  18. Classes et modules prédéfinie
    1. les commandes require et load

1) Introduction

Ruby est un langage interprété pur object, modulaire, et interface système (shell), inventé en 1993 au Japon par Yukihiro Matsumoto dit Matz

Pour télécharger ruby aller sur le site francophone http://www.ruby-lang.org/fr. Sous Debian, l'installation se fait avec la commande : apt-get  install  ruby. Pour lancer l’interpréteur ruby, sous Linux taper irb.

Ruby est un langage pure object, c'est à dire qu'il ne manipule que des objects à l'aide de variables. Ruby a été conçu avant tout pour le plaisir du développeur, afin de rendre le developpement davantage libre agréable et créateur, de réduire l'arbitraire des constructions informatiques et des logiques d'assemblage, en simplifiant la syntaxe pour qu'elle ne contiennent que l'essentiel du sense tout en laissant intacte l'interactivité et la lisibilité de l'objet. Ruby permet de transmettre à une méthode un bloc de code qui est une sorte de méthode anonyme, managée par la méthode appelante, et donne ainsi un moyen de décomposer une boucle de programmation en deux entitées reliées par un lien hiérarchique. C'est un langage object idéal pour les développeurs et pour tous ceux qui veulent s'initier à la logique de la programmation object et modulaire.

2) Variables et constantes

Un mot nu commençe par une lettre ou un underscore, et n'est composé que de lettres et de chiffres et d'underscores. Le mot nu est soit un mots-clefs du langage Ruby (voir liste ci-dessous), soit une variable locale, soit une méthode.

 Liste des mots-clefs

alias
and
begin
BEGIN
break
case
class
def
do
else
elsif
end
END
ensure
false
FALSE
for
if
in
module
next
nil
not
or
redo
rescue
retry
return
self
super
then
true
TRUE
undef
unless
until
when
while
yield

La variable, si elle est définie, contient une référence à un object. On définie une variable simplement en l'assignant à l'aide de l'opérateur = à une autre variable ou au résultat d'une méthode.

Les constantes sont des variables dont le nom commence par une majuscule. Elles sont initialisée comme des variables, et leur réassignation déclenche une erreur ou parfois un simple warning. Parcontre elle peuvent subire des modifications physiques.

Les variables globales sont préfixées par le caractère $

3) Symbôles et chaînes de caractères

3.1) Les symbôles

Les symboles commence par le caractère deux-points ":" suivi d'un mot nu sans guillemet, ou d'un mot nu entre guillemet. Les guillemets n'apporte aucune information supplémentaire. Ainsi le symbole :toto et le même que :"toto". Les symbôles peuvent être utilisés pour désigner des variables et des méthodes sans les évaluer.

3.2) Les chaînes de caractères

Les chaines de caractères sont entre guillement simple ou double. Ce sont des objects String. Noter que deux object String, s'ils n'occupent pas le même emplacement mémoire, sont des objects distincts même si leur contenue est identique. Ainsi l'instruction "Bonjour".equal?("Bonjour") retourne false. Car il s'agit de deux objects distincts qui peuvent subire chacun de leur coté des modifications physiques distinctes et qui ont finalement une vie distincte. Il n'en est pas de même avec les symbôles. L'instruction :Bonjour.equal?(:Bonjour) retourne true.

Parcontre l'opérateur == compare le contenue de l'object. L'instruction "Bonjour"=="Bonjour" retourne true.

4) Méthodes

4.1) Les appels de méthode

Une méthode est associé à un object, et peut posséder des arguments en nombres fixes ou variables. Le nom complet de la méthode se compose du nom de l'object sur lequel elle s'applique, suivi de l'opérateur point, suivi du nom générique de la méthode.

a.f désigne la méthode f de l'object a. Voici quelques exemples d'appels :

Appel sans argument a.f
a.f( )

Appel avec un argument a.f x
a.f(x)

Appel avec deux arguments a.f x,y
a.f(x,y)

Appel avec liste d'arguments a.f *x
a.f(*x)

Une séquence d'arguments telle que 5, "toto", :NP, y, f(3), n'est pas un object proprement dit. L'object est le tableau comprenant la séquence [5, "toto", :NP, y, f(3)]. Le sucre syntaxique permet d'affecter une séquence à une variable x, et la variable contiendra l'object tableau correspondant. x = 1,2 est identique à x = [1,2]. Pour concaténer des tableaux, on peut utiliser le symbôle * qui transforme le tableau en une séquence. Ainsi y = [*x, 9, *x] donnera [1,2,9,1,2] et nous pouvons écrire simplement y = *x,9,*x

La méthode peut ne pas avoir d'argument auquel cas on peut l'écrire sans séquence d'argument ou bien avec la séquence vide ( ). Dans le cas où elle possède des arguments, elle attend une séquence d'arguments. Et par exemple : a.f(x,y,z) est équivalent à u=x,y; a.f(*u,z)

4.2) Analayse syntaxique du langage Ruby

L'appel d'une méthode est composé du nom complet de la méthode, c'est à dire comprenant un objet, suivi de l'opérateur point, suivi du nom générique de la méthode, le tout suivie d'une liste d'arguments lorsqu'il y en a, séparés par des virgules, et il y a deux syntaxes possibles, la liste d'arguments est soit comprise entre parenthèse, ou soit elle ne l'est pas, comme dans l'exemple a.f(x,y,z) ou a.f x,y,z. Dans le premier cas c'est l'opérateur ( ) qui lie la méthode a.f à la liste de ses arguments x,y,z. Et l'opérateur virgule lie les arguments les uns à la suite des autres en une séquence. Dans le second cas moins classique le séparateur, qui est constitué d'au moin un caractère blanc, joue le rôle de l'opérateur de liaison qui associe la méthode a.f à la liste de ses arguments qui suit x,y,z. On aura donc remarqué que l'opérateur virgule est prioritaire sur l'opérateur de liaison.

Les arguments peuvent être à leur tour, un appel de méthode, qui sera évalué lors de l'appel et retournera un object, tel que a.f(x,a.g(y),z) ou a.f x,a.g(y),z ou a.f x,(a.g y),z. On en déduit que l'opérateur point est prioritaire sur l'opérateur virgule et sur l'opérateur de liaison et donc il est aussi prioritaire sur l'opérateur unaire gauche ( )

On considére que a.f retourne la méthode f de l'object a qui est appliqué en suite à la liste des arguments (x,y,z) à l'aide de l'opérateur unaire gauche ( ) ou de l'opérateur de liaison. La conception object se présente pourtant de façon inverse. La méthode de nom générique f appliqué aux arguments (x,y,z) retourne un message ("f",x,y,z) qui est ensuite envoyé à l'object a. Ces deux conceptions ce concilie dans l'implémentation de l'interpréteur ruby.

Lorsque l'object n'est pas mentionné, l'object par défault, désigné par le mot clé self, est utilisé. Ainsi l'appel de méthode f(x,y,z) correspond à l'appel self.f(x,y,z).

Dans les deux exemples d'appels f(x,f(y),z) ou f f(x),y,z, on remarque que l'opérateur unaire gauche ( ) est prioritaire sur l'opérateur virgule et sur l'opérateur de liaison

Dernière précision : Tous les caractères blancs ne sont pas des opérateurs de liaison, pour qu'un caractère blanc le soit il faut qu'il ne soit pas accolé à un point ou à une virgule ou à un point-virgule, et l'opérateur de liaison est alors constitué de tous les caractères blancs consécutifs.

Tableau des opérateurs selon leur priorité

Description symb.
Symb.
Exemple
Description exemple
Opérateur double double-point.
Donne accès à un espace de nom
::
A::X
A::X représente la constante X déclarée dans la classe ou le module A.
X peut être également une classe ou un module pouvant contenir à son tour d'autres constantes.
Opérateur point.
Donne accès à une méthode
.
a.f
a.f n'est pas un object, sauf si la méthode n'a pas d'argument et retourne un object, au quel cas a.f désigne l'object résultat de la méthode sans argument.
Opérateur d'application.
Relie l'entré d'une méthode à une liste d'arguments
( )
f(x)
Le contenu des parenthèses est un peu plus générale qu'un objet, c'est une liste d'arguments séparés par des virgules, une séquence. Et un argument peut être un object ou une liste d'instructions séparées par des point-virgules enserrée entre parenthèse qui une fois évalué retourne un object.
Opérateur virgule.
Constitue une liste d'arguments
,
x,y
x,y n'est pas un object mais constitue une séquence de deux objects qui peut être transmise comme liste d'arguments à une méthode, ou comme tableau [x,y] à une variable
Opérateur de liaison.
Relie l'entré d'une méthode à une liste d'arguments
 
f x
f x est évalué et retourne le résultat de la méthode f appliqué à la liste d'argument ici réduite à un seul élément x
Opération point-virgule.
Constitue une liste d'instructions
;
i;j
i;j est évalué dans l'ordre, l'instruction i d'abord puis j ensuite, et retourne le résultat de l'évaluation de la dernière instruction j

Les instructions suivantes sont équivalentes :

 f(x, g(y,z), t)

 f x, g(y,z), t
 f(x,(g y,z), t)
 f x,(g y,z), t
(f x,(g y,z), t)

La logique lispienne apparait alors naturellement, une liste où le premier élément désigne la méthode et les éléments suivants ses arguments, à ceci près que le premier élément est suivie d'un opérateur de liaison (caractères blancs) au lieu de l'opérateur virgule.

Un argument peut être également composé de plusieurs instructions séparées par des point-virgules (ou des passages à la ligne) et dont la liste est encadrée par des parenthèse (...). Dés qu'il y a un point-virgule (ou un passage à la ligne), ou un opérateur de liaison, la liste des instructions doit être encadrée par des parenthèses pour être acceptée comme argument et évaluée lors de l'appel.

4.3) Les listes de variables d'entrée

Pour définir une méthode on a besoin de déclarer une liste de variables d'entré, qui sont les entrées de la méthode et qui sont locales à sa définition. Ces variables d'entré sont analogues aux variables muettes dans une déclaration de fonction mathématique. Une liste de variables d'entrés peut comprendre des variables, des variables avec valeur par défaut placées en derniers, et une variable liste placée après et préfixée par *, et plus rarement une toute dernière variable Proc préfixée par &, chacune de nom distinct et séparée par des virgules.

Voici quelques exemples :

Liste de variables d'entré
Nombre d'entrés autorisées
Description

0
Liste de variables d'entré vide
x
1
Une variable d'entré.
x,y,z
3
Trois variables d'entré.
x=a
0,1
Une variable d'entré avec l'object a comme valeur par défaut
x,y=a,z=b
1,2,3
Trois variables d'entré dont la deuxième a pour valeur par défaut l'object a et la troisième a pour valeur par défaut l'object b
*x
0,1,2,3,4,5...
Une variable d'entré x qui regroupe dans un array la liste des entrés.
x=a,*t
2,3,4,5,6,7...
Deux variables d'entré dont la première à pour valeur par défaut l'object a et dont la quatrième est un array regroupant la liste des entrés supplémentaires.
&f
0 + bloc de code
Aucune variable d'entré mais un bloc de code
x,&p
1 + bloc de code
Une variable d'entré et un bloc de code
*x,&p
0,1,2,3,4,5...
+ bloc de code
Une variable d'entré x qui regroupe dans un array la liste des entrés, et un bloc de code

Une liste de variables d'entré sera notée dans la présente documentation par le signe ¤

4.4) Les blocs de code

Les instructions sont séparées par des point-virgules ou des passages à la ligne. Un point-virgule peut toujours être remplacé par un passage à la ligne et vis-versa. Une suite d'instructions séparées par des point-virgules tel que instruction1 ; instruction2 ; instruction3 sera notée par le signe ... que nous utiliserons couramment dans la présente documentation. Noter qu'il n'est pas nécessaire de placer un point virgule ni au début ni à la fin.

Un bloc de code est composé, éventuellement d'une liste de variables d'entrés enserrée entre pipe |¤| qui constitue la tête, suivie d'une suites d'instructions séparées par des point-virgules qui en constitue le corps, le tout enserrées entre accolades {|¤|...} ou entre les mots-clés do |¤| ... end .

Exemple de bloc de code :

{puts "Bonjour"}

do puts "Bonjour" end

{|x| print x} do |x| print x end
{|*x| print x.joint(", ")}

do |*x| print x.joint(", ") end

{|x=a,*y| puts x; puts y.length} do |x=a,*y| puts x; puts y.length end

Le bloc de code se situe toujours collé à la suite de l'appel d'une méthode, il ne doit pas y avoir de point virgule (ou de passage à la ligne) entre la méthode et le début du bloc de code. Le bloc de code est ainsi transmis à la méthode qui peut alors l'invoquer dans son propre code. Lorsque la méthode utilise un bloc de code qui lui est transmis, on dira qu'elle possède une connexion de bloc de code. Ce mécanisme constitue une caractéristique remarquable du langage Ruby.

4.5) Les appels de méthode avec bloc de code

Une méthode peut posséder une connexion de bloc de code, dans ce cas l'appel de la méthode doit nécessairement être suivie d'un bloc de code. Exemple d'appel d'une méthode f d'un object a avec bloc de code :

Appel sans argument avec un bloc de code
a.f do ... end
a.f {...}
a.f( ) do ... end
a.f( ) {...}

Appel avec deux arguments x, y, et avec un bloc de code
a.f x,y do ... end
a.f(x,y) do ... end
a.f(x,y) {...}

Contrainte syntaxique : Si un ou des arguments sont présents et ne sont pas regroupés entre parenthèses, le bloc de code transmis doit être de la forme do...end et non de la forme {...}.

4.6) Les méthodes send, respond_to?, method_missing(x)

L'appel de méthode a.f(x,y,z) correspond à l'envoi d'un message à l'object a, un message qui comprent le nom générique de la méthode sous forme d'un symbole :f (ou d'une chaine de caractères "f") suivi de ses arguments x,y,z, et éventuellement suivi d'un bloc de code lorsque la méthode a.f possède une connection de bloc de code. L'envoi d'un message correspond à la méthode send. Ainsi les codes suivants sont équivalents :

Appel de la méthode f de l'object a, sans argument et sans bloc de code a.f
a.send :f
a.send "f"
a.f()
a.send( :f)
a.send("f")

Appel de la méthode f de l'object a, avec deux arguments x, y, et sans bloc de code a.f x,y
a.send :f,x,y
a.send "f",x,y
a.f(x,y)
a.send( :f,x,y)
a.send("f",x,y)

Appel de la méthode f de l'object a, avec deux arguments x, y, et avec un bloc de code.

a.f x,y do ... end

a.send :f,x,y do ... end
a.send "f",x,y do ... end
a.f(x,y) do ... end
a.send(:f,x,y) do ... end
a.send("f",x,y) do ... end
a.f(x,y){...}
a.send(:f,x,y) {...}
a.send("f",x,y) {...}

Pour savoir si une méthode toto existe dans l'object a, on lance la méthode a.respond_to?("toto") qui returne true ou false le cas échéant.

Lorsque on appel une méthode a.f qui n'existe pas, l'object a va éxécuter la méthode a.method_missing("f",*x,&p) ou si elle n'existe pas, produire une erreur.

4.7) La définition d'une méthode singleton

La méthode a.f, (c'est à dire la méthode f de l'objet a), peut être définie ou redéfinie, pour l'unique object a, à l'aide de l'opérateur def a.f(¤) ... end ou def a.f ¤ ; ... end. La liste des variables d'entré ¤ qui peut être vide constitue la tête de la méthode et la liste des instructions ... qui peut être également vide constitue le corps de la méthode. Voici quelques exemples de définition de la méthode a.f

Préalable :
Création d'un object a
a = Object.new
Méthode sans argument
def a.f ; ... end
def a.f() ... end

Méthode avec deux arguments
def a.f x,y ; ... end
def a.f(x,y) ... end

Méthode avec un nombre d'arguments variable
La variable x est un array récupérant la liste des variables
def a.f *x ; ... end
def a.f(*x) ... end

Méthode avec au moins deux arguments et une valeur par défaut. Les arguments suivants sont récupérés dans la variable z qui est un array. Et si un seul argument est transmis alors la variable y est initialisé à la valeur b.
def a.f x,y=b,*z ; ... end
def a.f (x,y=b,*z)... end

Noter que les symbôles ¤ et ... sont des notations d'aide et doivent être remplacés respectivement par une liste de variables d'entré éventuellement vide et une liste d'instructions éventuellement vide.

Contrainte syntaxique : Si dans la définition d'une méthodes, la liste des variables d'entré est non vide et n'est par encadrée par des parenthèses, alors un point-virgule est nécessaire entre la liste des variables d'entré et la liste des instructions qui constituent le corps de la méthode. Ce point-virgule marque la fin de la liste des variables d'entré.

Dans le corps de la méthode, Toute variable locale autre que celles déclarées dans sa tête, doit être initialisée. Parcontre peuvent être présent des constantes (nom ayant pour première lettre une majuscule), des variable globales (nom commençant par un $), des variables d'instances (nom commençant par un @) et des variables de classe (nom commençant par @@).

Ces méthodes sont appelées méthodes singletons car elles ne s'applique qu'à un seul object. Pour un object a quelconque. La metaclasse de a est une pseudo classe qui regroupe les méthodes singleton de l'object a. On peut utiliser la méthode a.instance_eval{...}. Cette méthode permet de rajouter des méthodes singletons à l'object. Les méthodes définie dans la métaclasse de a sont les méthodes singleton de l'object a. On peut utiliser le mot clé class << a ; ... end. Cela réouvre la métaclasse de a pour y rajouter des méthodes d'instance qui joureont le rôle de méthodes singleton.

Ajouter à l'object a deux méthodes f et g
a.instance_eval do
  def f(x) ... end
  def g(x,y) ... end
end

a.instance_eval {
  def f(x) ... end
  def g(x,y) ... end
}

class << a
  def f(x) ... end
  def g(x,y) ... end
end

m = class << a ; self end
m.class_eval do
  def f(x) ... end
  def g(x,y) ... end
end

m = class << a ; self end
m.class_eval {
  def f(x) ... end
  def g(x,y) ... end
}

m est la classe singleton de a (aussi appelé métaclasse de a) et contient toutes les méthodes définie uniquement pour l'object a. L'appel d'une méthode singleton f peut se faire de deux manières a.f(x) ou a::f(x), et de même à partir de la métaclasse m.f(x) ou m::f(x)

La porté des variables locales s'arrètent dés que l'on commence un bloc def ou class ou module, mais pas lorsque on commence un bloc de code.

On peut ajouter un module M comme ensemble de méthodes singletons à l'aide de l'instruction class << a; include M end.

Une méthode singleton f de A peut être appellée par A::f

5) L'object main

L'appel d'une méthode f sans préciser l'object, fait implicitement référence à l'object en cours d'éxécution qui est référé par le mot-clef self. Dans la partie principale d'un programme Ruby, l'object en cours d'éxecution self, est l'object main. Les instructions principales sont donc relatives à l'object main. Néamoins l'object main n'est référencé par aucune variable ou constante. (On peut la référencer en executant par exemple l'instruction M = self). De même la définition d'une méthode f sans préciser de quel object il s'agit, définie la méthode f de l'object main. Ainsi les codes suivants sont équivalents :

Appel de la méthode f de l'objet main avec deux arguments x et y. f x,y
f(x,y)
self.f(x,y)
self.f x,y
main=self ; main.f(x,y)
main=self ; main.f x,y

Définition de la méthode singleton f de l'objet main avec deux arguments x et y. def f x,y ; ... end
def f(x,y) ... end
def self.f(x,y) ... end
def self.f x,y ; ... end
main=self ; def main.f(x,y) ... end
main=self ; def main.f x,y ; ... end

6) Le mot clé self

La variable self désigne l'object en cours par défaut.

Dans le corps d'une méthode singleton f de l'object a, la variable self désigne l'object a. Les appels de méthode sans préciser d'object, invoquées dans le corps de la méthode singleton f font donc implicitement référence à l'object a. Si elles n'existent pas, alors le mécanisme d'héritage va déplacer le contexte à un niveau au dessus pour trouver une méthode de même nom, les contextes les plus généraux étant celui de la classe Object, puis de son module Kernel, et en finale de l'object main.

Par exemple après avoir définie un object a et éxecuté l'instruction de définition suivante : def a.f ; g(h) end. La méthode a.f va d'abord rechercher la méthode a.g et si elle ne la trouve pas, va chercher la méthode g pour l'appliquer au résultat de la méthode a.h et si elle ne trouve pas cette méthode elle prendra la méthode h. Ainsi le résultat obtenu est le résultat de la première expression existante dans la liste suivante :

a.g(a.h)
a.g(h)
g(a.h)
g(h)

Il est toujours possible en définissant, redéfinissant ou supprimant après coup les méthodes a.g et a.h, ou g et h dans un niveau supérieur, de modifier le comportement de la méthode f.

Dans le corps d'une méthode singleton, le mot clé super permet d'appeler la méthode suivante de même nom rencontrée dans les niveaux supérieurs, avec les mêmes arguments, ou avec les arguments que l'on souhaite en les mettant explicitement super(x,y,z).

Il est possible d'attribuer le même nom à une méthode et à une variable. Dans ce cas c'est la variable qui prime et pour désigner la méthode il faut soit spécifier l'object qui peut être self ou soit spécifier des arguments entre paranthèse qui peuvent être réduit à une liste vide ( ). Par exemple, si x est à la fois une variable et une méthode, alors x désigne la variable et x( ), self.x ou a.x désigne la méthode.

7) Variables d'instance et variables de classe

Les variables d'instance sont la mémoire de l'object, son état. Leur nom commence par un @. Si elle ne sont pas initialisées leur valeur valent nil. Il suffit de les évoquer dans le corps d'une méthode singleton de l'object, ou d'une méthode d'instance de la classe de l'object, pour les créer.

Les variables de classe sont la mémoire de la classe de l'objet. Leur nom commence par un @@. Et elles doivent être initialisées. Ainsi deux objects a, b d'une même classe peuvent utiliser des variables de classe qui seront donc communes aux deux objects, et communes à tous les objects de cette classe.

8) Classes

Une classe A est un object qui possède la faculté de s'instancier, c'est à dire de créer des objects qui sont des instances de cette classe, des objects possédant des attributs désignés par les variables d'instance qui ont été définie dans la classe, et possédant des méthodes désignées par les méthode d'instance définie dans la classe.

La méthode new de l'object A va créer une instance de la classe A (ou si vous préférez, va créer un object de classe A). Le résultat peut être récupéré dans une variable, celle-ci contient alors une référence vers l'object nouvellement créé qui est mémorisé quelque part dans la mémoire du système. L'object nouvellement créé s'appelle une instance de la classe A, ou simplement un object de classe A. Il a été engendrés par la classe A à l'aide de la méthode A.new.

Création d'une instance de la classe A, ou d'un object de class A
A.new
Création d'un object de classe A,
et récupération d'une référence de cette objet dans la variable a.
a = A.new
Création d'un object de classe A,
et éxecution de la méthode f de l'object nouvellement créé,
le résultat est un objet dont une référence est récupérée dans la variable b.
b = A.new.f

Pour un object A, dire que c'est une classe signifie qu'il peut s'instancier à l'aide de la méthode new. Mais, dans les faits, cela est davantage. Les classes suivent un même model, et sont des instances d'une classe particulière appelé Class.

Class est la classe des classes. Pour créer une classe, on applique la méthode new de l'object Class, avec comme argument une classe appelée superclasse utilisé pour l'héritage simple, qui est par défaut la classe Object, suivie d'un bloc de code qui contient la définition des méthodes d'instances nouvelles ou redéfinies et qui constitue le corps de la classe.

Les modules sont similaires aux classes à part qu'ils ne s'instancient pas, c'est à dire qu'un module ne peut pas créer d'object. Les modules peuvent parcontre s'inclurent dans une classe. On inclut le module M dans la classe A simplement en ajoutant au corps de la classe A l'instruction include M. Dés lors les méthodes d'instance déclarées dans M sont utilisables par les objects de la classe. Et une classe possède un parent appelé sa superclasse mettant en oeuvre l'héritage simple.

Module est la classe des modules et est la supeclasse de Class.

Déscription
Classe
Module
Création d'une class A
A = Class.new {...} M = Module.new {...}
Création d'une classe B héritant de la classe A B = Class.new(A) {...}

On utilisera aussi les mot clef class...end.

Création d'une class A, ou ajout à la classe A
class A ; ... end module M ; ... end
Création d'une classe B héritant de la classe A, ou ajout à la classe B héritant de la classe A class B < A ; ... end

On utilisera aussi la méthode class_eval. Cette méthode permet de rajouter des méthodes d'instances à la classe.

Ajout à la classe A de deux méthodes f et g
A.class_eval do
  def f(x) ... end
  def g(x,y) ... end
end
M.class_eval do
  def f(x) ... end
  def g(x,y) ... end
end

A.class_eval {
  def f(x) ... end
  def g(x,y) ... end
}

M.class_eval {
  def f(x) ... end
  def g(x,y) ... end
}

Les classes et modules sont désignées par des constantes, leur nom commence donc par une majuscule.

L'object Object est la classe ancêtre de toutes les classes, ses méthodes d'instances sont donc disponibles pour tous les objects (saufs si elles sont explicitements ignorées). L'object Class est la classe de toutes les classes, elle hérite de la classe Module qui hérite de la classe Object. Chaque classe est une instance de la classe Class et hérite de la classe Module et donc aussi de la classe Object.

Class est sa propre instance. Module est Object sont des instances de Class.

8.1) Méthodes d'instance

Les méthodes d'instance d'une classe A sont les méthodes des objects de classe A définies au niveau de la classe. C'est à dire si f est une méthode d'instance de la classe A alors l'object a = A.new pourrra l'appliquer : a.f

Les méthodes d'instance d'un module M sont les méthodes des objects de classes incluant le module M, définies au niveau du module M. C'est à dire si f est une méthode d'instance du module M, inclue dans la classe A, alors l'object a = A.new pourrra l'appliquer : a.f

Pour ajouter une méthode d'instance à la classe A, on peut réouvrire la déclaration de la classe A (avec l'instruction class A ; ... end) ou utiliser la méthode class_eval (avec l'instruction A.class_eval do ... end).

Pour ajouter une méthode d'instance au module M, on peut réouvrire la déclaration du module M (avec l'instruction module M ; ... end) ou utiliser la méthode class_eval (avec l'instruction M.class_eval do ... end).

Dans la documentation, les méthodes d'instance sont noté comme A#f et les méthodes de classe comme A::f

8.2) Variables d'instance et variables de classe

Les variables d'instance d'une classe A (ou d'un module M) sont des variables mémorisées dans chaque object de classe A (ou de classe incluant le module M). Elles permettent aux object de se souvenir de leur état individuel et sont appelées attributs. Leur nom commence par @ et chaque object de classe A (ou de classe incluant le module M) possède une place mémoire distincte pour mémoriser leurs valeurs. Les méthodes d'instance de la classe A (ou du module M) peuvent manipuler ces variables qui se déclineront distinctement pour chaque object de la classe. Les méthodes singleton des objects de la classe A (ou d'une classe incluant le module M) peuvent également manipuler ces variables.

Les variables de classe sont la mémoire de la classe. Leur nom commence par un @@. Et elles doivent être initialisées. Les variables de classe sont communes à tous les objects de cette classe et peuvent être utilisées dans les méthodes d'instance ainsi que dans les méthodes de classe (déclaré aussi bien dans le corps d'une classe que d'un module) mais pas dans les méthodes singleton des objects de la classe.

La classe étant également un object, elle peut posséder des attributs qui seront désignés par des variables d'instances définie dans la classe de la classe ou dans une méthode singleton de la classe, c'est à dire dans une méthode de classe de la classe, et peuvent avoir le même nom, seul alors le contexte détermine s'il s'agit d'une variable d'instance de la classe ou d'une variable d'instance de la classe de la classe c'est à dire de la class Class.

8.3) exemples de classes

 

 

8.3) La méthode d'instance initialize

Cette méthode privée s'éxecute, lors de la création de l'object, avec les arguments et éventuellement le bloc de code qui sont transmis à la méthode new.

8.4) Les méthodes d'instance d'écriture et de lecture d'attribut

Les méthodes peuvent avoir un suffixe spécial suplémentaire parmis : "?", "!", "=". Sémantiquement le point d'intérogation "?" indique que la méthode interroge l'object et retourne une réponse, le point d'exclamation indique que la méthode effectue une modification physique de l'object, l'égalité indique que la méthode procède à une assignation de valeurs dans l'object. Il s'agit d'une convention donc préconisée mais non nécessaiement respectée.

Une méthode d'instance qui assigne une variable d'instance @x, c'est à dire qui assigne l'attribut d'un object, se note conventionnellement par le même nom que la variable d'instance, l'arrobase en moin, et avec le caractére égale en suffixe en plus, x=. Le signe égale est dans le nom de la méthode. Cette methode d'instance d'écriture se définie dans la classe par def x=(u) @x=u end.

Une méthode d'instance qui lit la variable d'instance @x, c'est à dire qui lit l'attribut d'un object, se note conventionnellement de même nom que la variable d'instance, l'arrobase en moin, x. Cette methode d'instance de lecture se définie dans la classe par def x( ) @x end.

Lorsque l'on procède à l'affection d'une variable d'instance @x d'un object a, en utilisant la méthode conventionnelle x= préalablement définie, pour l'affecter à la valeur b, tel que dans l'instruction suivante : a.x = b, cela correspond bien à l'appel de la méthode x= de l'object a appliqué à l'argument b. Le caractère espace qui existe entre le x et le signe égale est retiré, et c'est bien la méthode x= qui est appelée avec b comme argument.

Il n'en est pas de même pour les variables local de premier niveau. On pourra définir une variable x et une méthode x. L'instruction x retournera la valeur de x tandis que l'instruction x( ) exécutera la méthode x. Et on ne peut pas utiliser l'appel de méthode x= car celle-ci est toujours masquée par la commande d'affectation-création de la variable x (même en employant une liste d'arguments entre parenthèses), on utilisera donc l'appel a.x= ou sef.x= pour exécuter la méthode x= de l'object souhaité.

8.5) Les méthodes de la famille attr*

Dans le corps d'une classe ou d'un module, les méthodes suivantes permettent les raccourcis de code suivant :

Appel de méthode
Effet
Code équivalent

attr :x
Crée une méthode d'instance de lecture de l'attribut x
def x ; @x end
attr_reader :x

attr_writer :x
Crée une méthode d'écriture de l'attribut x
def x=(x) @x = x end

attr_accessor :x
Crée une méthode de lecture et d'écriture de l'attribut x
def x ; @x end
def x=(x) @x = x end
attr :x, true

8.6) Les méthodes de classe

Des méthodes définies pour un seul object s'appellent des méthodes singleton. Quand l'object concerné est une classe ces méthodes singletons sont alors appelées méthodes de classe. Et ces méthodes de classes sont transmisent par héritage aux sous-classes.

Pour ajouter une méthode singleton f à l'objet A, on peut utiliser l'instruction def A.f(¤) ... end ou utiliser la méthode instance_eval avec l'instruction A.instance_eval do def f(¤)... end end, ou réouvrire la déclaration de metaclass (avec les instruction class << A ; ... end. Mais comme A est une classe, il y a deux autre façons d'y ajouter des méthodes de classes, en utilisant une définition de méthode singleton avec le mot clé self, dans le corps de la classe :

Ajout à la classe A de deux méthodes de classe.

A.instance_eval do
  def f(x) ... end
  def g(x,y) ... end
end

A.instance_eval {
  def f(x) ... end
  def g(x,y) ... end
}
class A
  def self.f(x) ... end
  def self.g(x,y) ... end
end

class A
  class << self
    def f(x) ... end
    def g(x,y) ... end
  end
end

class << A
  def f(x) ... end
  def g(x,y) ... end
end

Une méthode de classe f de A peut être appellé par A.f ou A::f

La classe singleton de A peut s'obtenire par class <<A ; self end et s'appelle la métaclasse de A. Si une classe B hérite de la classe A, c'est à dire si B est une sous-classe de A, alors la métaclasse de B est également une sous-classe de A, et la méta-classe de B hérite de la métaclasse de A.

8.7) Les constantes, et le connecteur ::

Dans une classe ou un module A, les constantes sont définie simplement en les initialisant dans le corps de la classe ou du module. Les constantes d'une classe ou d'un module sont accessible via le connecteur ::. Par exemple A::X désigne la constante X de la classe A. la constante A::B::X désigne la constante X de la classe (ou module) B définie dans la classe (ou module) A.

class A
   class B
      X = 5
      ...
   end
   X = "hello"
   ...
end

L'object B est accessible via le connecteur ::. Ainsi pour créer un object de classe B on éxecutera l'instruction A::B.new On dira que la classe B est définie dans la classe A. En faite il s'agira de la classe A::B. Ainsi A fait office d'espace de nom et B peut être utilisé pour autre chose, désigner une autre classe....

L'analyse de la syntaxe nous montre que l'opérateur :: est prioritaire voir Tableau des opérateurs selon leur priorité

8.8) La hiérarchie des classes

L'héritage simple est mis en oeuvre. Les classes forment des ligniées qui s'assemblent pour former un arbre. La classe racine est la classe Object.

La classe de niveau juste au-dessus s'appelle la superclasse et celle d'un niveau juste en-dessous s'appelle une sous-classe. Toutes les instances d'une classe peuvent utiliser les méthodes d'instance définies dans la classe et également celles définies dans les classe supérieurs.

La hiérarchie des métaclasses est une hierarchie parallèle à la hiérarchie des classes.

8.9) Les modules

Les modules sont comme les classes, à part qu'ils ne peuvent pas s'instancier. Mais ils peuvent être ajoutés à une classe à l'aide du mot clef include. Une classe peut ainsi inclure plusieurs modules, et bénéficier des méthodes d'instance et de classe définie dans ces modules. Par contre l'héritage multiple n'est réservé qu'aux modules, une classe ne possède qu'une seul superclasse.

Un module M peut également être inclus dans la classe singleton de l'object a

class << a
  include M
  ...
end

Les modules sont des instances de la classe Module.

Class est une sous-classe de Module.

9) Le mot clé self et les contextes et la commande ancestors

Les appels de méthode peuvent ne pas préciser d'object auquel cas ils font implicitement référence à l'object self.

Un appel a.f s'ils n'existent pas, va rechercher dans les contextes supérieurs à l'object a, une méthode de même nom. L'ordre des contextes est le suivant. Par exemple :

class A
  include M
  include N
  ...
end

class B<A
  include O
  include P

  p ancestors
            // Cela affiche la hierarchie [B,P,O,A,N,M,Object,Kernel]
  ...
end


...

b=B.new
b.f

Hierarchie des contextes
self
Méthodes d'instance du module Kernel
Kernel
Méthodes d'instance de la classe Object
Object
...
...
Méthodes d'instance des modules de la superclass de la classe de l'object
M
N
Méthodes d'instance de la superclass de la classe de l'object
A
Méthodes d'instance des modules de la classe de l'object
O
P
Méthodes d'instance de la classe de l'object
B
Méthodes singleton de l'object
b

Les contextes les plus généraux étant celui de la classe Object, puis de son module Kernel, et en finale de l'object main.

A l'intérieur d'un bloc la valeur de self est la suivante :

Contexte
Exemple
self
Niveau superieur du programme
Tout code en dehors des autres blocs
main
Corps d'une classe

class A
  ...
end

A
Corps d'un module module M
  ...
end
M
Corps d'une méthode

def f(¤)
  ...
end

main
Corps d'une méthode singleton def a.f(¤)
  ...
end
a
Corps d'une méthode d'instance dans une classe

class A
  def f(¤) ... end
end

Une instance de A répondant à la méthode f.
Corps d'une méthode d'instance dans un module class M
  def f(¤) ... end
end
Une instance de classe qui inclut M et répond à la méthode f.

et la méthode de classe Module.ancestors produit un tableau comprenant la hierarchie des classes et modules.

10) Variables globales prédéfinies

Variable globale prédéfinies
Description
$!
L'object exception passé à la méthode +raise+
$@

La pile de trace générée par la dernière exception

$;
Séparateur par défaut pour la commande String.split
$,

String par défaut utilisé comme séparateur dans la commande Kernel.print et Array.join. Par defaut $,= nil, cela n'ajoute aucun texte.

$/
Le séparateur d'entré utilisé par la commande Kernel.gets. Vaut par défaut un passage à la ligne. Si nil, lit le fichier complet.
$\

String par défaut ajouté à la fin lors de la commande Kernel.print et IO.write. Vaut nil.

$.
Numéro de la dernière ligne lue du fichier d'entrée actuel.
$_
La dernière ligne lue par Kernel.gets ou
Kernel.readline.
$>
La destination de sortie pour Kernel.print et Kernel.printf. La valeur de défaut est $stdout.
$<
 
$$
Numéro du processus en cours d'exécution
$?
Statut de sortie du dernier processus enfant se trerminant.
$~
MatchData
$=
 
$*
 
$&
 
$`
 
$'
 
$+
 

11) Règles d'accès aux méthodes

Il existe trois règles d'accès : public, protected, private. Par défaut les méthodes sont publics. Dans le corps d'une classe ou d'un module, le mot clef public, protected, private, précise la règle d'accès des méthodes définies par la suite. Le mot clef peut être également utilisé avec une liste d'arguments, une liste de symbôles désignant des méthodes. Et les règles d'accès peuvent être redéfinis dans la classe, dans un module, ou dans une sous-classe....

Une méthode privées f d'un object a ne peut pas être appelée avec un recepteur explicite tel que a.f, mais avec un recepteur implicite f ou self.f. Ce faisant la méthode privé f de a ne peut pas être appelée par l'extérieur, mais uniquement par des méthodes définie dans la metaclasse de a, ou définie de façon anonyme dans la classe de a.

Une méthode protected f d'un object a ne peut être appelée avec un recepteur explicite a.f, que si le contexte en cours est celui d'un object de même classe que la classe de a, c'est à dire si self est égale à une instance de la classe dont a est une instance ou autrement dit si self est un frère de a. Ce faisant la méthode protected f de a ne peut pas être appelée par l'extérieur, mais uniquement par des méthodes définie dans la classe de a, ou dans la metaclasse de a, de facon anonyme ou non.

11.1 Les méthodes de niveau supérieur

La définition d'une méthodes sans préciser d'object définie une méthode privé du module Kernel. Elle ne peut donc être appelé avec un recepteur explicite, mais seulement avec un rectpeur implicite. Et comme Kernel est un module inclue dans la classe Object qui est l'ancêtre commun de toutes les classes. Un appel implicite à une méthodes de niveau supérieur, placé n'importe où dans le programme, finira toujours par trouver sa méthode de niveau supérieur si elle n'a pas été redéfinie dans une classe ou un module intermédiaire.

12) Classe singleton ou Metaclasses

Chaque object a possède une classe singleton invisible qui regroupe les méthodes singleton de l'object a. On peut rendre visible cette classe singleton par l'instruction d'affectation suivante : M = class << a; self end. Dés lors on peut ajouter des méthodes singleton f et g de l'object a par l'instruction M.class_eval do def f(¤)... end ; def g(¤) ... end end.

Les méthodes de classe sont des méthodes singleton définies sur des classes (Object de la classe Class). Les classes singleton des object classe sont généralement appelés métaclasses et sont soumisent à mécanisme implicite d'héritage, parallèle à l'héritage de classe.

13) Conditions, boucles et itérateurs

Voici les modèles de conditions, bouclee et itérateurs :

if cond1 then action1 elsif cond2 then action2 else action3 end   (le then peut être remplacé par un point-virgule ou un passage à la ligne)
unless cond1 then action1 else action2 end   (le then peut être remplacé par un point-virgule ou un passage à la ligne)

action if cond

action unless cond

action while cond

action until cond

while cond
  action
end

until cond
  action
end

begin
  action
end while cond

begin
  action
end until cond

case x
  when 0..5 then action1
  when 6 then action2
  when 6 : action2
  when cond then action2
  else action3
end

loop do
  action
  break if cond
end

for i in 5..8
  action
  next if cond1
  retry if cond2
end

(5..8).each do |i|
  action
end

(5..8).each { |i| action }
[2,4,7].each { |i| action }
"toto\nlili\nlulu" .each { |i| action }

for i in (5..8); action; end
for i in [2,4,7]; action; end
for i in "toto\nlili\nlulu"; action; end

14) Constructeurs littéraux

Certaines classes ne peuvent pas être instantié par la méthode new, et certaines classes sont dotées de constructeurs littéraux :

Classes
Constructeur littéral
Exemple
String
Guillements double ou simple
"fgh" ou 'fgh'
Symbole
Deux point au début
:fgh ou :'fgh' ou :"fgh"
Array
Crochet
[1,2,3]
Hash
Accolade
{"fgh" => :ab, [1,2] => 5}
Range
Deux ou trois points
1..5 ou 1...5
Regexp
Barre obliques
/([a-z]+)/

Tableau des priorités des opérateurs :

Classes
Constructeur littéral
Exemple
[]
[]=
Référence
Assignation
M[2]
M[2]=5
**
Exponentiation
2**5
!
~
+ (+@)
- (-@)
Négation
Complément
Plus unaire
Moins unaire
!(x==y)
~x
+x
-x
*
/
%
Multiplication
Division
Modulo
x*y
x/y
x%y
+
-
Plus
Moins
x+y
x-y
>>
<<
Shift droit
Shift gauche
x<<n
x>>n
&
Et x&y
^
|
Ou exclusif
Ou
x^y
x|y
<=
<
>
>=
Plus petit ou égale
Plus petit
Plus grand
Plus grand ou égale
x<=y
x<y
x>y
x>=y
<=>
==
===
!=
=~
~!

Egale

Différent

 
x<=>y
x==y
x===y
x!=y
x=~y
x~!y
&&
Et logique x>y && x>z
||
Ou logique x>y || x>z
..
...
Range inclusive
Range exclusive
2..5
2...5
?:
if-then-else x<y ? 5 : 2
= %= /=
+= |= &=
>>= <<=
*= &&=
||= **=
Assignement x=2
x%=5
x*=y
x&&=y
x||=y
defined?
If defined defined? x
not
Négation not x<y
or
and
Ou logique
Et logique
x<y or x<z
x<y and x<z
if unless
while until
Conditionnel x+=1 if x<y
x=f(x) while x<50
begin/end
Bloque

15) Les méthodes Kernel::eval et Object#instance_eval et Module#class_eval et Module#define_method

La porté des variables locales s'arrètent dés que l'on commence un bloc def ou class ou module, mais pas lorsque on commence un bloque de code, sauf naturellement si la tête du bloc de code contient cette variable.

eval("...") évalue les instructions ... au niveau supérieur, c'est à dire dans le contexte où self = main. La variable globale $SAFE peut être fixé de 0 à 4 et indique un niveau de sécurité limittant les possibilitées de la méthode eval.

a.instance_eval("...") ou a.instance_eval {...} évalue les instructions ... au niveau de l'object a, considéré comme un simple object, c'est à dire dans le contexte où self = a. Ainsi a.instance_eval("@x") retourne la valeur de l'attribut x de l'objet a.

A.class_eval("...") ou A.class_eval {...} évalue les instructions ... au niveau de la classe A, considéré comme une classe, c'est à dire dans le contexte où self = A. Ainsi A.class_eval("@@x") retourne la valeur de la variable de classe x de la classe A. (class_eval est un alias de module_eval)

class A
  u=12
  define_method(:f){|x| puts u; u=u+x}
end

La méthode privée define_method permet de définir une méthode, avec comme argument le nom de la méthode et comme bloque de code la tête et le corps de la méthode. La variable u à l'intérieur de la méthode est liée à la variable u local du bloc class A, elles constituent une et une seul même variable. Une tel définition de méthode liant des variables locals s'appelle une fermeture (clossure).

L'instruction A.class_eval {define_method("f"){|x| puts x; u=u+x}} permet d'ajouter une méthode d'instance f à la classe A, ayant un argument, et agissant sur la variable local u, qui est une variable local du bloc dans lequel est executé cette instruction.

16) les objects invocables (callable object)

Un object est invocable s'il possède une méthode call qui exécute du code présent dans l'object. Les principaux objects invocables sont les objects méthode, les object Proc, et les object lambda.

16.1 Les Proc et les lambda

u=12
p = Proc.new{|x| puts u; u=u+x}

Cela crée un object Proc avec ici un argument, qui agira sur une variable local u, qui est une variable local du bloc dans lequel est exécuté cette instruction. Une tel définition de Proc liant des variables locals s'appelle une fermeture (closure). Quant vous ouvrer une fermeture (en l'appelant) elle contient les valeurs actuelles des variables locales du blocs où elle a été créé.

p.call(2) va exécuter la procédure en maintenant les liaisons avec les variables locales présente dans le blocs où à été créé la procédure. La variable u est celle du bloc où à été créé la procédure et non celle du bloc où est invoqué la procédure p.call(2).

Quasiment la même instruction avec un object lambda u=12; p = lambda {|x| puts u; u=u+x} et quelque part ailleur dabs un autre bloc l'appel p.call(2).

Une différence tient dans le fait que l'object lambda est une méthode anonyme et donc que l'instruction return va terminer l'exécution de la méthode anonyme lambda, alors que l'object Proc est un bloc de code exécutable, objectisé pour répondre à la méthode call, qui lorsqu'il rencontre l'instruction return, va terminer la méthode qui a fait appel à lui.

Une autre différence consiste dans le nombre d'arguments qui est stricte pour l'appel d'une méthode lambda comme pour n'importe quel méthode, et qui est beaucoup plus souple pour l'appel d'une Proc où les arguments en trop sont ignorés et les arguments manquants sont remplacés par des valeurs nil.

16.2 Le préfixe &

Il est possible de transmettre à une méthode f, un object Proc ou lambda p, comme bloc de code. Il suffit pour cela d'ajouter p préfixé par &, comme dernier argument de l'appel de la méthode sans bloc de code. Aisni f(x,&p) est un appel de la méthode f avec l'argument x et le bloc de code correspondant à celui de la Proc p ou de la méthode lambda p.

Il est possible de déclarer une méthodes de tel sorte que le bloc de code transmis lors de ses appels soit récupéré sous forme d'object Proc à l'interieur d'une variable. def f(x,&p) p.call(x) end va définire une méthode f. Et lors de l'appel f(2){...} ou f(2,&q), le bloc de code transmis va être converti en un object Proc p, puis cette object sera invoquer avec x comme pararmètre (qui est ici une entré de la méthode, l'argument d'appel de la méthode).

Dans le corps de la méthode, l'instruction p.call(x) peut être remplacer par yield(x) qui agit directement sur le bloc de code transmis, alors que p.call(x) utilise l'object p, qui est le bloc de code transmis converti en object Proc.

Une lambda ou un Proc q peut être transmit comme un bloc de code à une méthode f par l'appel f(2,&p). Ainsi les deux instructions suivantes sont équivalentes :

f(7,&Proc.new{|x| puts x})
f(7) {|x| puts x}

16.3 Les méthodes sont des objects

La méthode method d'un object a, permet de récupérer les méthodes sous forme d'object

m=a.methode(:f)
m.call(x,y)

m récupère la méthode de nom "f" lié à l'object a, sous forme d'object et qui peut être éxécuté en lui appliquant la méthode call.

La méthode unbind permet de délié une méthode de son object tout en restant attaché à sa classe où elle est définie.

m0 = m.unbind

m0 est la méthode de nom "f" délié de l'object a, et pouvant être relié à un object de même classe que a ou d'une classe descendantes de la classe de a. On peut obtenir directement une méthode d'instance non lié à un object précis grace à la méthode de class instance.method

m0 = A.instance_method(:f)

m0 est la méthode de nom "f" lié à aucun object, et pouvant être relié à un object de classe A ou d'une classe descendantes de A.

La méthode bind permet de lié une méthode d'instance définie dans une classe à un object de la même classe ou d'une classe descendantes.

m1 = m0.bind(b)
m1(x,y)

m1 est une méthode relié à l'object b de classe A ou d'une classe descendante de A.

L'instruction c.f(x,y) éxecute la méthode f de l'object c. Cette méthode a pu être redéfinie à un niveau intermediaire, soit dans la classe de l'object c ou d'une classe parente mais descendante d'une classe A qui nous intéresse. Pour appeler une méthode f de l'object c mais précisement celle d'une classe ancêtre A, et non celle redéfinie dans une classe intermédiaire, executez l'instruction

A.instance_method(:f).bind(c).call(x,y).

Ceci peut constituer une méthode d'instance d'une class C descendante de la class A.

class C < A
  def call_A
    A.instance_method(:f).bind(self).call
  end
end

17 Aspects de construction

17.1 Méthode Module#included

Pour déclencher une action lorsque le module M est inclus dans une classe A. Cette action doit être définie dans le module en question par la méthode de classe included(c)c récupère la référence de la classe dans laquel le module s'inclut. Voici un exemple :

module M
  def self.included(c)
    puts "Je viens d'être inclus dans la classe #{c}"
  end
end

On peut utiliser cela pour rajouter une méthode de classe f à la classe qui ionclut le module M

module M
  def self.included(c)
    def c.f(x) ... end
  end
end

17.2 Méthode Class#inherited

Pour déclencher une action lorsque on créé une sous-classe B d'une classe A. Cette action doit être définie dans la classe A en question par la méthode de classe inherited(c)c récupère la référence de la classe qui engendre une sous-classe. Voici un exemple :

class A
  def self.included(c)
    puts "#{self} viens d'être sous-classé dans la classe #{c}"
  end
end

17.3 Méthode Module#const_missing

C'est une méthode comparable à method_missing, elle est appelé à chaque fois que l'on appel une constante inconnue dans une classe ou un module. Pour déclencher une action lorsque une constante inconnue est rencontrée dans la classe ou le module, on utilisera donc la méthode const_missing(c)c récupère le nom de la constante en question. Voici un exemple :

class C
  def self.const_missing(c)
    puts "#{c} est non définie. Nous l'initialisons à la valeur 12"
    const_set(c,12)
  end
end

La première fois que l'on appellera une constante non définie A à l'aide de la commande C::A, le message "A est non définie. Nous l'initialiserons à la valeur 12" s'affichera et l'instruction const_set(c,12) s'exécutera initialisant la constante de nom contenue dans c, à la valeur 12.

18 Classes et modules prédéfinie

18.1 les commandes require et load

La commande load "prog.rb" va charger le script ruby prog.rb et l'exécuter à cette place de tel sorte qu'il sera comme présent à la place de l'instruction load "prog.rb". La commande require "prog.rb" fait la même chose à ceci près que si un premier require "prog.rb" a été rencontré avant, il n'est pas rechargé une seconde fois.

Pour utiliser le module Math dans le programme principale sans avoir à préfixé les commandes par Math::, taper simplement include Math

 

"Ruby et Rails, Le guide Ruby des développeurs Rails" (David A. Black), 2006 CampusPress

 

 

 

Trois suffixes spéciaux autorisés pour les méthodes : "?", "!", "="

 

 

__FILE__

__LINE__

=begin

=end

defined?

 

 

Object est la classe mère de toutes les classes, ses methodes sont donc disponibles pour tous les objects, saufs si elles sont explicitement ignorées. Object inclus le module Kernel. Module est une sous-classe d'Object. Classe est une sous-classe de Module.

 

object_id
respond_to?
send

 

def f(x) yield(2, x, 4) end => nil
f(3){|x,y,z| x+10*y+100*z} => 432

 

http://www.pipoetmario.com/index.php

Instance methods:
Array(x) : x.to_ary || x.to_a || [x]

Float(x) : Conversion des objects Numeric. Pour les autres x.to_f

Integer(x) : Conversion des objects Numeric. Pour les String les préfixes 0 (octal), 0x (hexadécimal), 0b (binaire) sont honorés. Pour les autres x.to_int et x.to_i

Pathname : ?

String(x) : Conversion des objetcs en appelant leur méthode to_s

URI : ?

` ... ` : Commande système et retourne le résultat de la sortie standart. (Voir %x{...} et $? )

abort : Kernel.exit(1) : Kernel::abort : Process::abort : Kernel.abort

at_exit{...} : Convertie un block en Proc (en le liant au point d'appel) et l'enregistre pour l'executer quand le programme s'arrète.
at_exit do ... end

autoload(:s,"prog") : Lorsque le module s est appelé la première fois, executer le fichier "prog"

autoload?

binding

block_given?

callcc

caller

catch

chomp

chomp!

chop

chop!

eval

exec

exit

exit!

fail

fork

format

getc

gets

global_variables

gsub

gsub!

iterator?

lambda

load

local_variables

loop

method_missing

open

open

open_uri_original_open

p

pp

pretty_inspect

print

printf

proc

putc

puts

raise

rand

readline

readlines

require

scan

scanf

select

set_trace_func

sleep

split

sprintf

srand

sub

sub!

syscall

system

test

throw

trace_var

trap

untrace_var

warn

warn

y

 

Array, Float, Integer, Pathname, String, URI, `, abort, at_exit, autoload, autoload?, binding, block_given?, callcc, caller, catch, chomp, chomp!, chop, chop!, eval, exec, exit, exit!, fail, fork, format, getc, gets, global_variables, gsub, gsub!, iterator?, lambda, load, local_variables, loop, method_missing, open, open, open_uri_original_open, p, pp, pretty_inspect, print, printf, proc, putc, puts, raise, rand, readline, readlines, require, scan, scanf, select, set_trace_func, sleep, split, sprintf, srand, sub, sub!, syscall, system, test, throw, trace_var, trap, untrace_var, warn, warn, y

 

Oject --|--> Module ----> Class
|--> IO ----> File
|--> String
|--> Array
|--> Hash
|--> Regexp
|--> Numeric --|--> Integer --|--> Fixnum
| |--> Bignum
|--> Float
Range
Symbol

x.kind_of? Integer