Menu
Coddy logo textTech

Liaison avec __index

Fait partie de la section Object Oriented Programming du Journey Lua de Coddy — leçon 7 sur 70.

Vous avez une table prototype avec des propriétés et des méthodes, mais comment faire en sorte qu'un nouvel objet l'utilise réellement ? La réponse réside dans la métaméthode __index.

Lorsque vous accédez à une clé qui n'existe pas dans une table, Lua renvoie normalement nil. Cependant, si la table possède une métatable avec un champ __index, Lua ira chercher à cet endroit à la place. En configurant __index pour qu'il pointe vers votre prototype, toutes les clés manquantes sont automatiquement trouvées dans le prototype :

local Dog = {
    species = "Canis familiaris",
    legs = 4
}

function Dog:bark()
    print("Woof!")
end

-- Créer une instance vide
local myDog = {}

-- Le lier au prototype
setmetatable(myDog, { __index = Dog })

print(myDog.species)  -- Résultat : Canis familiaris
myDog:bark()          -- Résultat : Woof!

La table myDog est complètement vide, pourtant l'accès à myDog.species fonctionne. Lorsque Lua ne trouve pas species dans myDog, il vérifie le __index de la métatable et le trouve dans Dog.

C'est le fondement de la programmation orientée objet en Lua. L'instance peut avoir ses propres données uniques, tandis que le comportement partagé réside dans le prototype. Dans la leçon suivante, vous apprendrez comment encapsuler ce modèle dans une fonction constructeur propre.

challenge icon

Défi

Facile

Mettons maintenant la métaméthode __index en pratique ! Vous allez créer un prototype et y lier une instance, permettant à l'instance d'accéder à des propriétés et des méthodes qu'elle ne possède pas directement.

Vous organiserez votre code sur deux fichiers :

  • Robot.lua : Définissez une table prototype Robot avec :
    • Un champ model défini sur "RX-100"
    • Un champ batteryLevel défini sur 100
    • Une méthode :status() qui affiche l'état actuel du robot
    Retournez la table à la fin du fichier.
  • main.lua : Importez le module Robot, puis créez une table d'instance vide et liez-la au prototype Robot en utilisant setmetatable avec __index. Cela permet à votre instance vide d'accéder à tout ce qui provient du prototype.

Vous recevrez une entrée : un nom à attribuer à votre instance de robot.

Après avoir lié l'instance au prototype :

  1. Attribuez le nom reçu en entrée au champ name de votre instance (cela devient unique à l'instance)
  2. Appelez la méthode :status() sur votre instance

Votre méthode :status() doit afficher le texte dans ce format exact :

[name] ([model]) - Battery: [batteryLevel]%

Par exemple, si l'entrée est Sparky, la sortie doit être :

Sparky (RX-100) - Battery: 100%

Remarquez comment l'instance possède son propre name, mais accède à model et batteryLevel à partir du prototype via le lien __index.

Aide-mémoire

La métaméthode __index permet aux objets d'hériter des propriétés et des méthodes d'une table prototype.

Lorsque vous accédez à une clé qui n'existe pas dans une table, Lua vérifie si la table possède une métatable avec un champ __index. Si c'est le cas, Lua recherche la clé dans la table spécifiée par __index.

Pour l'ier une instance à un prototype :

local Prototype = {
    property = "value"
}

function Prototype:method()
    print("Method called")
end

-- Create an instance
local instance = {}

-- Link to prototype using __index
setmetatable(instance, { __index = Prototype })

-- Access prototype properties and methods
print(instance.property)  -- Output: value
instance:method()         -- Output: Method called

La table d'instance peut être vide, tout en pouvant accéder à toutes les propriétés et méthodes du prototype. L'instance peut également avoir ses propres propriétés uniques qui remplacent ou étendent le prototype.

Ce modèle est le fondement de la programmation orientée objet en Lua, où les instances partagent le comportement d'un prototype tout en conservant leurs propres données uniques.

Essayez vous-même

-- Lire l'entrée
local name = io.read()

-- Charger le module Robot
local Robot = require('Robot')

-- TODO: Créer une table d'instance vide

-- TODO: Lier l'instance au prototype Robot en utilisant setmetatable avec __index

-- TODO: Assigner le nom saisi au champ name de votre instance

-- TODO: Appeler la méthode :status() sur votre instance
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Object Oriented Programming