Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox



POO : L'héritage sous Director

Compatible Director MX2004. Cliquer pour en savoir plus sur les compatibilités.Par glurp (Elliot Coene), le 31 août 2009

Note : Il est recommandé de consulter le tutorial sur la POO avant de se lancer dans celui de l'héritage.

Qu'est-ce que l'héritage ?

L'héritage est une notion importante de la programmation orientée objet. Il permet une lecture à double sens de la programmation. Nous avons l'habitude de travailler en système descendant tel qu'un monde, contenant une maison, contenant des pièces, contenant des objets où chaque “plus gros” contient et gère le “plus petit”. Avec l'héritage, il devient possible de travailler dans l'autre sens tel que la cuisine, le salon ou la salle de bain sont toutes des pièces (tronc commun) mais possèdent aussi leurs fonctions spécifiques. Ainsi, plutôt que de faire de “if” ou des “case” au sein d'un même objet pour différencier les comportements de divers types, nous pouvons leurs spécifier une base commune, puis préciser leurs caractéristiques propres. En POO, nous parlerons de classes filles et de classes mères (même si sous Director, tous portent le nom de script parent).

L'héritage sous Director

Comparativement au C++, il y a quelques différences importantes. Pour une fois, Director se montrera “moins souple” car il ne permet pas l'héritage multiple ni la redéfinition de fonction. L'héritage multiple, comme son nom l'indique, permet de définir plusieurs tronc commun. La redéfinition de fonction consiste à redéfinir une fonction mère dans la classe fille, remplaçant l'ancienne par la nouvelle. Si l'héritage multiple n'est que rarement utilisé (il est source d'erreur et n'est vraiment nécessaire que pour les très gros projets), la redéfinition de fonction permet aux “bases communes” (classes mères) de pouvoir être utilisées comme objets indépendants (une pièce pourrait être une pièce sans que nous ayons à spécifier son type). Il faudra donc être vigilant et tenir compte que ces restrictions propres à Director.

Comment ça marche ?

Ce n'est pas très compliqué ni très différent de la POO. Tous les scripts (mères et filles) doivent être en mode “script parent”. Sous Director, tous les scripts parents possèdent une propriété commune (utilisée ou non) qui porte le nom de “ancestor”. Si vous tapez ce mot clés, vous verrez qu'il est coloré en vert. Cet ancestor est un pointeur vers le script mère. Il suffit de le déclarer et de le définir pour qu'automatiquement le script fille hérite de toutes les fonctions et propriétés de la classe mère. Les deux scripts ne faisant plus qu'un, les fonctions sont appelées normalement telles que me.fonction(). Une particularité cependant ; les propriétés de la classe mère ne sont pas directement accessibles par leur nom mais doivent être appelées comme les fonctions telles que me.propriete. Ceci n'étant pas très respectueux des principes de la POO, nous préférerons utiliser des accesseurs (voir le tutorial sur la POO).

Exercice pratique

Nous allons faire une mise en pratique simple pour comprendre le fonctionnement de l'héritage. Préparons deux carrés de 40*40 pixels, un rouge et un bleu, le premier suivras la souris sur l'axe des X et le deuxième sur l'axe de Y. Pour l'exemple, nous créons aussi un carré gris qui sera notre tronc commun (la classe mère).

Nous ne plaçons rien sur la timeline, uniquement un script de comportement appelé “stop” sur la frame 20 et contenant la boucle

on exitframe me
  go to the frame
end

Premier script, la classe mère (que nous appelons “carre_script”) ;

property pSprite, pPosition
 
on new me
 
  me.init()
 
  return me
 
end
 
on findEmptyChannel me
 
  tChannel = 150  
  repeat with i = 1 to 150
    if sprite(i).puppet = false and sprite(i).membernum = 0 then
      tChannel = i
      exit repeat
    end if
  end repeat
 
  put tChannel
 
  return tChannel
 
end
 
on init me
 
  -- Position et représentation "de base" --
 
  pPosition = point(320,240)
 
  pSprite = me.findEmptyChannel()  
  channel(pSprite).makescriptedsprite(member("carregris"), pPosition)
 
end
 
on moveXY me, tX, tY
  -- Déplacement en X Y --
  pPosition = pPosition + point(tX, tY)
  sprite(pSprite).loc = pPosition
end
 
----------------
-- Accesseurs --
----------------
on getposition me
  return pPosition
end
 
---------------
-- Mutateurs --
---------------
on setMember me, tMember
  sprite(pSprite).member = tMember
end

Ensuite nous spécifions les script filles rouge_script et bleu_script ;

property ancestor -- Déclaration indispensable --
 
on new me 
 
  -- Héritage --
  ancestor = script("carre_script").new()
 
  me.initRouge()
 
  return me
 
end
 
on initRouge me
 
  -- Change la représentation --
  me.setMember(member("carrerouge"))
 
  -- L'actorList permet aux script de recevoir la temporisation stepFrame --
  (the actorlist).add(me)
 
end
 
on stepframe me
 
  -- Déplace en X --  
  tPosition = me.getposition()  
  tDiffX = _mouse.mouseh - tPosition[1]  
  me.moveXY(tDiffX, 0)
 
end

Et bleu ;

property ancestor -- Déclaration indispensable --
 
on new me 
 
  -- Héritage --
  ancestor = script("carre_script").new()
 
  me.initBleu()
 
  return me
 
end
 
on initBleu me
 
  -- Change la représentation --
  me.setMember(member("carrebleu"))
 
  -- L'actorList permet aux script de recevoir la temporisation stepFrame --
  (the actorlist).add(me)
 
end
 
on stepframe me
 
  -- Déplace en Y --
 
  tPosition = me.getposition()
 
  tDiffY = _mouse.mousev - tPosition[2]
 
  me.moveXY(0, tDiffY)
 
end

Ne reste plus qu'à initialiser tout ça dans un script global de Movie ;

on startmovie
 
  -- Initialise les objets --
  script("rouge_script").new()
  script("bleu_script").new()
 
end
 
on stopmovie
 
  -- Vide l'actorList --
  the actorlist = []
 
end

Lancer le programme et vous verrez les deux carrés se déplacer.

Ce petit exercice n'est évidemment qu'un exemple, il aurait pu fonctionner en spécifiant un type “rouge” ou “bleu” aux objets pour différencier leurs comportements dans un “if”… Mais dans de plus gros projets, il est très pratique d'avoir des “modèles” pouvant s'imbriquer les uns dans les autres.

Les possibilités de l'héritage sont nombreuses, il ne reste plus pour vous qu'à les découvrir ;-)

heritage_cast.jpg

Sources Director MX 2004 :