La création d’Elfes doit se faire à l’aide de la méthode create()
. Voici des
exemples simples pour se familiariser avec l’écriture.
Imaginons des Elfes où le premier (Valinor
qui est un singleton) veut créer
les Elfes (Elrond
et Galadriel
) sous la forme d’instances.
class Galadriel extends Elf {
state = new GaladrielState();
async create(id, desktopId = null) {
this.do();
return this;
}
async hi(who) {
this.log.dbg(`Hi ${who}`);
}
}
class Elrond extends Elf {
state = new ElrondState();
async create(id, desktopId = null) {
this.do();
return this;
}
async hello(who) {
this.log.dbg(`Hello ${who}`);
}
}
class Valinor extends Elf.Alone {
async init() {
const desktopId = 'valinor@system';
const elrondId = 'elrond@valinor';
const galadrId = 'galadriel@valinor';
try {
const elrond = await new Elrond(this).create(elrondId, desktopId);
const galadriel = await new Galadriel(this).create(galadrId, desktopId);
await elrond.hello('Galadriel');
await galadriel.hi('Elrond');
} finally {
await this.kill(elrondId);
await this.kill(galadrId);
/* Il est aussi possible de faire :
* await this.kill([elrondId, galadrId]);
*/
}
}
}
Cet exemple présente plusieurs caractéristiques importantes. Ici nous voyons
deux Elfes d’instance, ainsi qu’un Elfe de type singleton. Le singleton
Valinor
créé les deux Elfes Elrond
et Galadriel
, les utilise puis les
dispose. Ce mécanisme se nomme le create
/ kill
pattern et n’a rien de bien
sorcier. Il faut néanmoins bien comprendre que le kill
est explicite avec un
singleton, car justement, personne ne tue un singleton et nous ne désirons pas
avoir une fuite d’Elfes.
Quand une instance créé un Elfe, il n’est pas nécessaire d’appliquer le create
/ kill
pattern car dans ce cas, le fait de tuer le premier Elfe va
automatiquement tuer les Elfes sous-jacents (bien entendu, pour autant qu’aucun
autre Elfe en dépende également).
class Galadriel extends Elf {
state = new GaladrielState();
async create(id, desktopId = null) {
this.do();
return this;
}
async hi(who) {
this.log.dbg(`Hi ${who}`);
}
}
La quête awake()
va créer un Elfe qui sera automatiquement attaché à cette
instance d’Elrond
pour le feed valinor@system
.
class Elrond extends Elf {
state = new ElrondState();
async create(id, desktopId = null) {
this.do();
return this;
}
async hello(who) {
this.log.dbg(`Hello ${who}`);
}
async awake() {
const galadriel = await new Galadriel(this).create('galadriel@valinor');
await galadriel.hi('Elrond');
await this.hello('Galadriel');
}
}
class Valinor extends Elf.Alone {
async init() {
const desktopId = 'valinor@system';
const elrondId = 'elrond@valinor';
try {
const elrond = await new Elrond(this).create(elrondId, desktopId);
await elrond.awake();
} finally {
await this.kill(elrondId);
}
}
}
Dans cet exemple, Elrond
créer Galadriel
puis communique avec cette Elfe. Ce
cas introduit également une autre particularité. Quand un Elfe souhaite exécuter
ses propres quêtes, il peut simplement les appeler via this
comme dans
l’exemple avec await this.hello()
.
Attention, n’oubliez pas ce qui est expliqué dans le chapitre Qui sont’il. Les classes elfiques ne sont pas des classes javascript standards, et les appels sur les méthodes ne sont pas directs mais passent par les bus Xcraft.
Cela peut paraître étrange dit ainsi mais rien n’empêche qu’un certain type d’Efle créer un autre Elfe de même type. Il est possible de le faire comme dans les exemples ci-dessus; un chemin plus directe peut être utilisé, voyez ci-dessous.
class Galadriel extends Elf {
state = new GaladrielState();
async create(id, desktopId = null) {
this.do();
const galadrielBis = await this.create(`${id}@bis`);
await galadrielBis.hi('Galadriel');
return this;
}
async hi(who) {
this.log.dbg(`Hi ${who}`);
}
}
La différence avec les create()
précédents est d’avoir écrit :
const galadrielBis = await this.create(`${id}@bis`);
Au lieu de :
const galadrielBis = await new Galadriel(this).create(`${id}@bis`);