Tester le type d’un objet avec l’opérateur is()

Le Lua sur TI-Nspire permet de créer facilement des classes avec la fonction class() qui permet également de créer des classes héritées, basées sur le modèle de la classe mère avec quelques différences. Malheureusement, étant donné que le concept de classes n’est que superficiel, il n’existe ni fonction ni syntaxe spécifique pour travailler avec certains types de classes. Dans ce tutoriel nous allons voir comment reproduire le fonctionnement de l’opérateur is() présent dans d’autres langages de programmation orienté objet, tel que le C#.

L’opérateur is() permet de distinguer un objet qui a été créée à partir d’une classe spécifique, mais aussi des classes mères (Etant donné que l’héritage en Lua est une pure copie de la classe mère, il n’est pas possible de gérer l’héritage avec l’opérateur is que nous allons créer).

Voici un petit exemple de ce qu’on désire faire :

function is(obj, class)
  -- we are going to create it
end
 
A = class()
function A:init(x)
  self.x = x
end
 
B = class(A)
function B:init(x)
  self.x = x * 2
end
 
t = { A(1),  B(1) }
for k, v in pairs(t) do
  if is(v, A) then
    print("A class, value = "..v.x)
  elseif is(v, B) then
    print("B class, value = "..(v.x / 2))
  end
end

Nous voyons ici très bien l’intérêt : si nous stockons dans un tableau des objets issus de classes héritées donc portant certaines propriétés en commun, nous voulons dans certains cas distinguer si l’objet est issu de telle ou telle classe.

Mais alors comment écrire la fonction is() dans ce cas ? Rajouter un champ ? Non ! En effet, le fonction class() affecte déjà certains champs sans que vous ne le sachiez. class() affecte le champ __index de la table (ou objet), et il contient un pointeur vers la classe mère. Lorsque vous faites a = A() , a.__index est égal à A.__index (en terme de références).

Ainsi, voici la fonction is()

function is(obj, class)
  return obj.__index == class.__index
end

NB : Comme la limite entre classes et objet est assez floue en Lua (contrairement à d’autres langages où un objet est instancié par une classe), il est possible de tester si deux objets appartiennent à la même classe mère de la même manière :

A = class()
function A:init() end
a = A()
b = A()
is(a, b) -- returns true

Laisser un commentaire