Quelle est la différence entre les mots-clés «const» et «final» dans Dart?


Réponses:


237

Il y a un article sur le site Web de Dart et il l'explique assez bien.

Final:

"final" signifie une affectation unique: une variable ou un champ final doit avoir un initialiseur. Une fois une valeur attribuée, la valeur d'une variable finale ne peut pas être modifiée. final modifie les variables .


Const:

"const" a une signification un peu plus complexe et subtile dans Dart. const modifie les valeurs . Vous pouvez l'utiliser lors de la création de collections, comme const [1, 2, 3], et lors de la construction d'objets (au lieu de nouveaux) comme const Point (2, 3). Ici, const signifie que tout l'état profond de l'objet peut être déterminé entièrement au moment de la compilation et que l'objet sera gelé et complètement immuable.

Les objets Const ont quelques propriétés et restrictions intéressantes:

Ils doivent être créés à partir de données qui peuvent être calculées au moment de la compilation. Un objet const n'a pas accès à tout ce que vous auriez besoin de calculer au moment de l'exécution. 1 + 2 est une expression const valide, mais new DateTime.now () ne l'est pas.

Ils sont profondément, transitivement immuables. Si vous avez un champ final contenant une collection, cette collection peut toujours être modifiable. Si vous avez une collection const, tout ce qu'elle contient doit également être const, de manière récursive.

Ils sont canonisés . C'est un peu comme un internement de chaîne: pour une valeur const donnée, un seul objet const sera créé et réutilisé quel que soit le nombre de fois que les expressions const sont évaluées.


Qu'est-ce que cela signifie?

Const:
Si la valeur que vous avez est calculée à l'exécution ( new DateTime.now()par exemple), vous ne pouvez pas utiliser de const pour elle. Cependant, si la valeur est connue au moment de la compilation ( const a = 1;), vous devez utiliser constover final. Il existe 2 autres grandes différences entre constet final. Premièrement, si vous utilisez const, vous devez le déclarer static constplutôt que juste const. Deuxièmement, si vous avez une constcollection, tout ce qui s'y trouve est dedans const. Si vous avez une finalcollection, tout ce qui s'y trouve ne l' est pasfinal .

Final:
final devrait être utilisé constsi vous ne connaissez pas la valeur au moment de la compilation, et elle sera calculée / récupérée au moment de l'exécution. Si vous voulez une réponse HTTP qui ne peut pas être modifiée, si vous voulez obtenir quelque chose à partir d'une base de données ou si vous voulez lire à partir d'un fichier local, utilisez final. Tout ce qui n'est pas connu au moment de la compilation devrait être finalterminé const.


Cela étant dit, les deux constet finalne peuvent pas être réaffectés, mais les champs d'un finalobjet, tant qu'ils ne le sont pas constou final, peuvent être réaffectés (contrairement à const).


3
Le mot clé const est utilisé pour représenter une constante de compilation. Les variables déclarées à l'aide du mot-clé const sont implicitement finales.
Arun George

1
@Meyi, quand devons-nous utiliser constet quand final? Connaissez-vous une sorte de cas d'utilisation de ces modificateurs?
CopsOnRoad

4
@CopsOnRoad, vous pouvez regarder cette vidéo Dart Const vs Final
Lemuel Ogbunude

2
Cette dernière phrase le résume si bien. Merci pour ça.
Yster

Devrions-nous même nous soucier que const est une option? Le gain de performance est-il vraiment perceptible?
CodeGrue

64

Const

La valeur doit être connue au moment de la compilation , const birthday = "2008/12/26"
ne peut pas être modifiée après l'initialisation.


Final

La valeur doit être connue au moment de l' exécution , final birthday = getBirthDateFromDB()
ne peut pas être modifiée après l'initialisation.


11
L'explication la plus simple et la meilleure.
Ankur Lahiry

1
aimé celui-ci :)
Faisal Naseer

43

Réponses consolidées @Meyi et @ faisal-naseer et comparaison avec peu de programmation.

const:

Const mot clé utilisé pour créer une variable pour stocker une valeur constante au moment de la compilation . La valeur de la constante de temps de compilation est une valeur qui sera constante lors de la compilation :-)

Par exemple, 5une constante de temps de compilation. Alors que DateTime.now()ce n'est pas la constante de temps de compilation. Parce que cette méthode renverra l' heure à laquelle la ligne est exécutée au moment de l'exécution. Nous ne pouvons donc pas affecter le DateTime.now()à une constvariable.

const a = 5;
// Uncommenting below statement will cause compile time error.
// Because we can't able to assign a runtime value to a const variable
// const b = DateTime.now();

Doit être initialisé sur la même ligne .

const a = 5;
// Uncommenting below 2 statement will cause compilation error.
// Because const variable must be initialized at the same line.
// const b;
// b = 6;

Toutes les déclarations mentionnées ci-dessous sont acceptables.

// Without type or var
const a = 5;
// With a type
const int b = 5;
// With var
const var c = 6;

La variable const au niveau de la classe doit être initialisée comme ci-dessous.

Class A {
    static const a = 5;
}

La variable const au niveau de l'instance n'est pas possible .

Class A {
    // Uncommenting below statement will give compilation error.
    // Because const is not possible to be used with instance level 
    // variable.
    // const a = 5;
}

L'autre utilisation majeure de constest utilisée pour rendre l' objet immuable . Pour rendre un objet de classe immuable, nous devons utiliser le mot-clé const avec le constructeur et rendre tous les champs finaux comme mentionné ci-dessous.

Class A {
    final a, b;
    const A(this.a, this.b);
}

void main () {
    // There is no way to change a field of object once it's 
    // initialized.
    const immutableObja = const A(5, 6);
    // Uncommenting below statement will give compilation error.
    // Because you are trying to reinitialize a const variable
    // with other value
    // immutableObja = const A(7, 9);

    // But the below one is not the same. Because we are mentioning objA 
    // is a variable of a class A. Not const. So we can able to assign
    // another object of class A to objA.
    A objA = const A(8, 9);
    // Below statement is acceptable.
    objA = const A(10, 11);
}

nous pouvons utiliser le mot-clé const dans une liste .

const a = const [] - Une variable a initialisée comme constcontenant une liste d' constobjets (c'est-à-dire que la liste ne doit contenir que des constantes de temps de compilation et des objets immuables). Nous ne pouvons donc pas attribuer aune autre liste .

var a = const [] - Une variable a initialisée comme varcontenant une liste d' constobjets . Donc , nous pouvons en mesure d'assigner une autre liste à la variablea .

Class A {
    final a, b;
    const A(this.a, this.b);
}

class B {
    B(){ // Doing something }
}

void main() {
    const constantListOfInt = const [5, 6, 7,
                 // Uncommenting below statement give compilation error.
                 // Because we are trying to add a runtime value
                 // to a constant list
                 // DateTime.now().millisecondsSinceEpoch
              ];
    const constantListOfConstantObjA = const [
        A(5, 6),
        A(55, 88),
        A(100, 9),
    ];
    // Uncommenting below 2 statements will give compilation error.
    // Because we are trying to reinitialize with a new list.
    // constantListOfInt = [8, 9, 10];
    // constantListOfConstantObjA = const[A(55, 77)];

    // But the following lines are little different. Because we are just
    // trying to assign a list of constant values to a variable. Which 
    // is acceptable
    var variableWithConstantList = const [5, 6, 7];
    variableWithConstantList = const [10, 11, 15];
    var variableOfConstantListOfObjA = const [A(5, 8), A(7, 9), A(10, 4)];
    variableWithConstantList = const [A(9, 10)];
}

final:

mot clé final également utilisé pour que la variable contienne une valeur constante . Une fois initialisé, nous ne pouvons pas modifier la valeur.

final a = 5;
// Uncommenting below statement will give compilation error.
// Because a is declared as final.
// a = 6;

Toutes les déclarations mentionnées ci-dessous sont acceptables.

// Without type or var
final a = 5;
// With a type
final int b = 5;
// With var
final var c = 6;

Peut attribuer une valeur d'exécution .

// DateTime.now() will return the time when the line is getting
// executed. Which is a runtime value.
final a = DateTime.now();
var b = 5;
final c = b;

La variable finale au niveau de la classe doit être initialisée dans la même ligne.

Class A {
    static final a = 5;
    static final b = DateTime.now();
}

La variable finale au niveau de l'instance doit être initialisée dans la même ligne ou lors de l'initialisation du constructeur. La valeur sera mise en mémoire lors de la création de l'objet.

Class A {
    final a = 5;
}

// Constructor with a parameter.
Class B {
    final b;
    B(this.b);
}

// Constructor with multiple parameter.
Class C {
    final c;
    C(this.c, int d) {
        // Do something with d
    }
}

void main() {
    A objA = new A();
    B objB = new B(5);
    C objC = new C(5, 6);
}

Attribution d' une liste .

final a = [5, 6, 7, 5.6, A()];
// Uncommenting Below statement will give compilation error.
// Because we are trying to reinitialize the object with another list.
// a = [9.9, 10, B()];

20

Prolonger la réponse par @Meyi

  • La variable finale ne peut être définie qu'une seule fois et elle est initialisée lors de l'accès (par exemple à partir de la section de code ci-dessous si vous utilisez la valeur de biggestNumberOndiceseulement, la valeur sera initialisée et la mémoire sera affectée).
  • const est de nature finale en interne, mais la principale différence est que sa constante de temps de compilation qui est initialisée lors de la compilation même si vous n'utilisez pas sa valeur, elle sera initialisée et prendra de la place en mémoire.

  • La variable des classes peut être finale mais pas constante et si vous voulez une constante au niveau de la classe, rendez-la statique const.

Code:

void main() {

    // final demonstration
    final biggestNumberOndice = '6';
    //  biggestNumberOndice = '8';     // Throws an error for reinitialization

    // const
    const smallestNumberOnDice = 1;

}

class TestClass {

    final biggestNumberOndice = '6';

    //const smallestNumberOnDice = 1;  //Throws an error
    //Error .  only static fields can be declared as constants.

    static const smallestNumberOnDice = 1;
}

2
Je pense qu'une meilleure façon de poser la question est de savoir quand préférer l'initialisation du runtime à l'initialisation au moment de la compilation ...
Faisal Naseer

et pour cela vous pouvez consulter la réponse @Meyi et aussi visiter le lien de l'article de son post c'est merveilleux :)
Faisal Naseer

2

Les deux finalet constempêchent une variable d'être réaffectée (similaire au finalfonctionnement en Java ou au constfonctionnement en JavaScript).

La différence a à voir avec la façon dont la mémoire est allouée. La mémoire est allouée pour une finalvariable à l'exécution et pour une constvariable au moment de la compilation. Le finalmodificateur devrait être le plus couramment utilisé, car de nombreuses variables de programme n'auront pas besoin de mémoire car la logique du programme ne les appellera pas à être initialisées. Avec une constvariable, vous dites essentiellement à l'ordinateur: "Hé, j'ai besoin de mémoire pour cette variable à l'avance parce que je sais que j'en aurai besoin."

Penser à eux de cette manière permet de mieux comprendre les différences dans leur utilisation syntaxique. Principalement qu'une finalvariable peut être une variable d'instance, mais a constdoit être une staticvariable sur une classe. En effet, les variables d'instance sont créées au moment de l'exécution et les constvariables - par définition - ne le sont pas. Ainsi, les constvariables d'une classe doivent l'être static, ce qui signifie simplement qu'une seule copie de cette variable existe sur une classe, que cette classe soit instanciée ou non.

Cette vidéo le décompose assez simplement: https://www.youtube.com/watch?v=9ZZL3iyf4Vk

Cet article va plus en profondeur et explique une différence sémantique très importante entre les deux, c'est-à-dire qu'il finalmodifie les variables et constmodifie les valeurs, ce qui revient essentiellement à ne pouvoir initialiser que des constvaleurs qui sont dérivables au moment de la compilation.

https://news.dartlang.org/2012/06/const-static-final-oh-my.html


2

finalet consten fléchettes sont déroutants au niveau où nous pensons que les deux sont les mêmes.

Voyons leurs différences:

PS J'ai inclus l'image au lieu du texte car je ne pouvais pas facilement tabuler les informations au format Stackoverflow .md.


1

Si vous venez, C++alors constdedans Dartest constexprdedans C++et finaldedans Dartest constdedans C++.

Ce qui précède s'applique uniquement aux types primitifs. Cependant, les Dartobjets marqués finalsont modifiables en termes de membres.


2
Sorte de. Je pense que vous pourriez dire cela pour les types primitifs mais pas pour les objets. consten C ++ est presque toujours utilisé pour spécifier qu'un objet n'est pas modifiable via une référence ou un pointeur spécifique. finaldans Dart n'empêche pas l'objet de subir une mutation via cette variable.
jamesdlin

0

Vous ne pouvez pas initialiser un en constutilisant un final. Par exemple :

  final myConst = 1;
  const myFinal = 2;

  final a = myConst; // possible
  final b = myFinal; // possible
  const c = myConst; // this is not possible
  const d = myFinal; // possible

0

Quand utiliser quel mot-clé?

Un exemple simple pour les deux: Utilisez final: si vous ne savez pas quelle sera sa valeur au moment de la compilation. Par exemple, lorsque vous pouvez avoir besoin d'obtenir des données à partir d'une API, cela se produit lors de l'exécution de votre code.

Utilisez const: si vous êtes sûr qu'une valeur ne sera pas modifiée lors de l'exécution de votre code. Par exemple, lorsque vous déclarez une phrase qui reste toujours la même.

https://itnext.io/difference-between-const-and-final-in-dart-78c129d0c573

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.