0
votes

Constructeur acceptant (1) liste de chaîne; (2) Array de Str; (3) Carte

Je voudrais étendre le constructeur de manière à ce que les deux lignes avec le niveau et la couleur puissent être décisées. C'est-à-dire que l'on peut générer une énumération avec une carte et une énumération avec une liste (cette seconde est faible priorité).

Je pourrais renoncer à la variante de fonctionnement (non engagée) et à accepter uniquement la matrice, puis vérifiez si les éléments sont des chaînes ou des objets, mais cette solution ne serait pas aussi niche que celle que je recherche (tant qu'elle existe ...). xxx


6 commentaires

Dans le second cas, quel devrait être cela.values ​​? Comme dans, comment le cela.values.indexof (valeur) fonctionne-t-il?


Test valeurs [0] doit être typeof chaîne ou array.isarray .


VOTRE OBJECT VERSION LITHERAL contient certaines erreurs de syntaxe. Je soupçonne que vous vouliez dire nouvel énum ({'1': {txt: 'h1'}, '2': {txt: 'h2'}, '3': {txt: "h3 '}}) ?


@Adiga dans le deuxième cas this.values ​​ ne peut pas être propre, mais il sera juste ignoré


@Bergi exactement, je vais corriger le q


@Bergi concernant votre premier commentaire, je comprends; Je vais essayer maintenant


3 Réponses :


1
votes

Vous pouvez vérifier si les valeurs [0] code> est une matrice. Ensuite, vérifiez si les valeurs [0] code> est un objet. Je ne sais pas quelles sont les valeurs pour ce scénario. Le scénario restant est destiné à taille code>. Dans ce cas, attribuez directement ceci.values ​​= valeurs code>

p>

class Enum {

  constructor(...values) {
    if (Array.isArray(values[0]))
      this.values = values[0]
      
    else if (typeof values[0] === 'object')
      this.values = Object.keys(values[0]) // not sure
      
    else this.values = values;
  }

  check(value) {
    return this.values.indexOf(value) !== -1;
  }
}

const enums = {
    Size: new Enum('small', 'big', 'huge'),
    Level: new Enum({'1': {txt: 'h1'}, '2': {txt: 'h2'}, '3': {txt: 'h3'}}),
    Color: new Enum(['small', 'big', 'huge']),
};

console.log(enums)


2 commentaires

Pour les cas de tableau et d'objet, on peut également lancer une exception si valeurs.length> 1 - juste pour attraper des erreurs accidentelles


Merci. Cette solution ne préserve pas le dictionnaire, il extrait les touches. Je l'ai obligé explicitement, mais pour économiser les informations supplémentaires séparément ne serait pas aussi agréable.



2
votes

Les constructeurs "polymorphes" sont une mauvaise idée surtout, car ils sont difficiles à programmer (comme vous le savez déjà) et aussi plus difficiles à suivre dans le code. Au lieu de cela, je suggère d'utiliser des fonctions d'usine spécialisées pour chaque type d'argument possible. Exemple:

p>

class Enum {
    constructor(pairs) {
        for (let [name, val] of pairs)
            this[name] = val;
    }

    static from(names) {
        return new this([...names.entries()].map(([k, v]) => [v, k]));
    }

    static of(...names) {
        return this.from(names);
    }


    static fromObject(obj) {
        return new this(Object.entries(obj));
    }
}


const enums = {
    Size: Enum.of('small', 'big', 'huge'),
    Level: Enum.fromObject({'first': {txt: 'h1'}, 'second': {txt: 'h2'}, 'third': {txt: 'h3'}}),
    Color: Enum.from(['red', 'orange', 'blue']),
    Flags: new Enum([['read', 1], ['write', 2], ['execute', 4]])
};

console.log(enums.Size.huge)
console.log(enums.Color.orange)
console.log(enums.Level.third)
console.log(enums.Flags.execute)


0 commentaires

0
votes

Voici une solution à l'aide de @bergi.

p>

class Enum {
  constructor (...keys) {
    this.keys = null;
    this.map = null;
    if (typeof keys[0] === 'string') {
      this.keys = keys;
    } else if (Array.isArray(keys[0])) {
      this.keys = keys[0];
    } else {
      this.map = keys[0];
    }
  }

  check (key) {
    if (this.keys != null) {
      return this.keys.indexOf(key) !== -1;
    } else if (this.map != null) {
      return key in this.map;
    } else {
      return null;
    }
  }

  value (key) {
    if (this.keys) {
      return (this.keys.indexOf(key) !== -1 ? key : null);
    } else if (this.map) {
      return (key in this.map ? this.map[key] : null);
    } else {
      return null;
    }
  }
}

const enums = {
  Size: new Enum('small', 'big', 'huge'),
  Color: new Enum(['red', 'green', 'blue']),
  Level: new Enum({
    '1': {
      text: 'h1',
    },
    '2': {
      text: 'h2',
    },
    '3': {
      text: 'h3',
    },
  }),
};

console.log(enums.Size.check('big'));
console.log(enums.Size.value('big'));
console.log(enums.Size.check('aaa'));
console.log(enums.Size.value('aaa'));
console.log(enums.Color.check('green'));
console.log(enums.Color.value('green'));
console.log(enums.Level.check('1'));
console.log(enums.Level.value('1').text);
console.log(enums.Level.check('8'));
console.log(enums.Level.value('8'));


1 commentaires

Je recommanderais de supprimer la touche instance de chaîne . Personne n'utilise des instances d'emballage primitives, elles sont considérées comme une mauvaise pratique.