133 votes

Comment créer des variables privées dans Dart ?

Je veux créer une variable privée mais je ne peux pas.

Voici mon code :

void main() {
  var b = new B();
  b.testB();    
}

class A {
  int _private = 0;

  testA() {
    print('int value: $_private');
    _private = 5;
  }
}

class B extends A {
  String _private;

  testB() {
    _private = 'Hello';
    print('String value: $_private');
    testA();
    print('String value: $_private');
  }
}

Lorsque j'exécute ce code, j'obtiens le résultat suivant :

String value: Hello
int value: Hello
Breaking on exception: type 'int' is not a subtype of type 'String' of 'value'.

Je ne reçois pas non plus d'erreur ou d'avertissement lorsque je modifie ce code source.

Comment créer une variable privée dans Dart ?

232voto

mezoni Points 2361

Extrait de la documentation de Dart :

Contrairement à Java, Dart ne possède pas les mots-clés public, protected et private. Si un identificateur commence par un trait de soulignement _ il est privé de sa bibliothèque.

Les bibliothèques ne fournissent pas seulement des API, mais constituent une unité de confidentialité : les identifiants qui commencent par un trait de soulignement _ ne sont visibles qu'à l'intérieur de la bibliothèque.

Quelques mots sur les bibliothèques :

Chaque application Dart est une bibliothèque, même si elle n'utilise pas de directive de bibliothèque. Les directives import et library peuvent vous aider à créer une base de code modulaire et partageable.

Vous avez peut-être entendu parler de la part qui vous permet de diviser une bibliothèque en plusieurs fichiers Dart.

91voto

Chris Buckett Points 6329

La confidentialité dans Dart existe au niveau de la bibliothèque, plutôt qu'au niveau de la classe.

Si vous deviez placer la classe A dans un fichier de bibliothèque séparé (par exemple, le fichier de bibliothèque de la classe A), vous seriez en mesure de le faire, other.dart ), tels que :

library other;

class A {
  int _private = 0;

  testA() {
    print('int value: $_private');  // 0
    _private = 5;
    print('int value: $_private'); // 5
  }
}

puis l'importer dans votre application principale, par exemple :

import 'other.dart';

void main() {
  var b = new B();
  b.testB();    
}

class B extends A {
  String _private;

  testB() {
    _private = 'Hello';
    print('String value: $_private'); // Hello
    testA();
    print('String value: $_private'); // Hello
  }
}

Vous obtenez le résultat attendu :

String value: Hello
int value: 0
int value: 5
String value: Hello

27voto

Bensal Points 1233

Sur dart ' _ est utilisé avant le variable name pour le déclarer comme private . Contrairement aux autres langages de programmation, ici private ne signifie pas qu'elle n'est disponible que pour la classe dans laquelle elle se trouve, privée signifie qu'elle est accessible dans le fichier où il se trouve y non accessible aux autres fichiers .

16voto

AaronF Points 753

La meilleure réponse pour l'instant est sans aucun doute la bonne.

Je vais essayer d'entrer dans les détails dans cette réponse.

Je vais répondre à la question, mais commencez par ceci : Ce n'est tout simplement pas la façon dont Dart doit être écrit, en partie parce que les membres privés de la bibliothèque facilitent la définition d'opérateurs tels que == . (Les variables privées d'un deuxième objet n'ont pas pu être vues pour la comparaison).

Maintenant que nous avons réglé cette question, je vais commencer par vous montrer comment il faut faire (library-private au lieu de class-private), puis je vous montrerai comment rendre une variable class-private si vous y tenez vraiment. C'est parti.

Si une classe n'a pas à voir les variables d'une autre classe, vous pouvez vous demander si elles ont vraiment leur place dans la même bibliothèque :

    //This should be in a separate library from main() for the reason stated in the main method below.

    class MyClass {
      //Library private variable
      int _val = 0;

      int get val => _val;
      set val(int v) => _val = (v < 0) ? _val : v;

      MyClass.fromVal(int val) : _val = val;
    }

    void main() {
      MyClass mc = MyClass.fromVal(1);
      mc.val = -1;
      print(mc.val); //1

      //main() MUST BE IN A SEPARATE LIBRARY TO 
      //PREVENT MODIFYING THE BACKING FIELDS LIKE:
      mc._val = 6;
      print(mc.val); //6
    }

Cela devrait être bon. Cependant, si vous vraiment veulent des données de classe privées :

Bien que techniquement vous ne soyez pas autorisé à créer des variables privées, vous pourrait l'émuler en utilisant la technique de fermeture suivante.

(CEPENDANT, vous devriez considérer AVEC PRÉCISION si vous en avez vraiment besoin et s'il n'existe pas un meilleur moyen, plus proche de Dart, de faire ce que vous essayez d'accomplir).

    //A "workaround" that you should THINK TWICE before using because:
    //1. The syntax is verbose.
    //2. Both closure variables and any methods needing to access
    //   the closure variables must be defined inside a base constructor.
    //3. Those methods require typedefs to ensure correct signatures.

    typedef int IntGetter();
    typedef void IntSetter(int value);

    class MyClass {
      IntGetter getVal;
      IntSetter setVal;

      MyClass.base() {
        //Closure variable
        int _val = 0;

        //Methods defined within constructor closure
        getVal = ()=>_val;
        setVal = (int v) => _val = (v < 0) ? _val : v;
      }

      factory MyClass.fromVal(int val) {
        MyClass result = MyClass.base();
        result.setVal(val);
        return result;
      }
    }

    void main() {
      MyClass mc = MyClass.fromVal(1);
      mc.setVal(-1); //Fails
      print(mc.getVal());

      //On the upside, you can't access _val
      //mc._val = 6; //Doesn't compile.
    }

Alors oui. Soyez prudent et essayez de suivre les meilleures pratiques de la langue et tout devrait bien se passer.

EDIT

Apparemment, il y a une nouvelle syntaxe typedef qui est préférée pour Dart 2. Si vous utilisez Dart 2, vous devriez l'utiliser. Ou, encore mieux, utiliser les types de fonctions en ligne.

Si vous utilisez la seconde, elle sera moins verbeuse, mais les autres problèmes demeurent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X