Qual è la differenza tra le parole chiave "const" e "final" in Dart?


Risposte:


237

C'è un post sul sito Web di Dart e lo spiega abbastanza bene.

Finale:

"final" significa assegnazione singola: una variabile o un campo finale deve avere un inizializzatore. Una volta assegnato un valore, il valore di una variabile finale non può essere modificato. finale modifica le variabili .


const:

"const" ha un significato un po 'più complesso e sottile in Dart. const modifica i valori . Puoi usarlo quando crei raccolte, come const [1, 2, 3] e quando costruisci oggetti (invece di nuovi) come const Point (2, 3). Qui const significa che l'intero stato profondo dell'oggetto può essere determinato interamente al momento della compilazione e che l'oggetto sarà congelato e completamente immutabile.

Gli oggetti Const hanno un paio di proprietà e restrizioni interessanti:

Devono essere creati da dati che possono essere calcolati in fase di compilazione. Un oggetto const non ha accesso a tutto ciò che dovresti calcolare in fase di esecuzione. 1 + 2 è un'espressione const valida, ma il nuovo DateTime.now () non lo è.

Sono profondamente, transitivamente immutabili. Se si dispone di un campo finale contenente una raccolta, tale raccolta può essere comunque modificabile. Se hai una collezione const, anche tutto ciò che deve essere const deve essere ricorsivo.

Sono canonicalizzati . Questo è un po 'come lo string interning: per ogni dato valore const, verrà creato e riutilizzato un singolo oggetto const indipendentemente da quante volte vengono valutate le espressioni const.


Che cosa significa questo?

Const:
Se il valore si dispone è calcolato in fase di esecuzione ( new DateTime.now()per esempio), è possibile non utilizzare un const per esso. Tuttavia, se il valore è noto al momento della compilazione ( const a = 1;), è necessario utilizzare constover final. Ci sono altre 2 grandi differenze tra conste final. In primo luogo, se lo stai utilizzando const, devi dichiararlo come static constnon solo const. In secondo luogo, se hai una constcollezione, tutto ciò che è dentro è dentro const. Se hai una finalcollezione, tutto ciò che non lo è final.

Finale:
final deve essere utilizzato constse non si conosce il valore in fase di compilazione e verrà calcolato / acquisito in fase di esecuzione. Se si desidera una risposta HTTP che non può essere modificata, se si desidera ottenere qualcosa da un database o se si desidera leggere da un file locale, utilizzare final. Tutto ciò che non è noto al momento della compilazione dovrebbe essere finalfinito const.


Detto questo, entrambi conste finalnon possono essere riassegnati, ma i campi in un finaloggetto, purché non lo siano consto final, possono essere riassegnati (a differenza const).


3
La parola chiave const viene utilizzata per rappresentare una costante di compilazione-tempo. Le variabili dichiarate usando la parola chiave const sono implicitamente finali.
Arun George,

1
@Meyi, quando dovremmo usare conste quando final? Conosci una sorta di caso d'uso per questi modificatori?
CopsOnRoad,

4
@CopsOnRoad potresti vedere questo video Dart Const vs Final
Lemuel Ogbunude,

2
L'ultima frase lo riassume davvero così bene. Grazie per quello
Yster

Dovremmo anche preoccuparci che const sia un'opzione? L'aumento delle prestazioni è davvero percepibile?
CodeGrue

64

const

Il valore deve essere noto al momento della compilazione , const birthday = "2008/12/26"
non può essere modificato dopo l'inizializzazione.


Finale

Il valore deve essere noto in fase di esecuzione , final birthday = getBirthDateFromDB()
non può essere modificato dopo l'inizializzazione.


11
La spiegazione più semplice e migliore.
Ankur Lahiry,

1
mi è piaciuto molto :)
Faisal Naseer il

43

Risposte @Meyi e @ faisal-naseer consolidate e confronto con poca programmazione.

const:

parola chiave const utilizzata per creare una variabile per memorizzare un valore costante di tempo di compilazione . Il valore della costante del tempo di compilazione è un valore che sarà costante durante la compilazione :-)

Ad esempio 5è una costante di tempo di compilazione. Mentre DateTime.now()ciò non è costante di tempo di compilazione. Perché questo metodo restituirà il momento in cui la linea viene eseguita in fase di esecuzione. Quindi non possiamo assegnare DateTime.now()a una constvariabile.

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();

Dovrebbe essere inizializzato sulla stessa riga .

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;

Tutte le dichiarazioni menzionate di seguito sono accettabili.

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

La variabile const a livello di classe deve essere inizializzata come di seguito.

Class A {
    static const a = 5;
}

La variabile const a livello di istanza non è possibile .

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'altro uso principale di constviene utilizzato per rendere immutabile l' oggetto . Per rendere immutabile un oggetto classe dobbiamo usare la parola chiave const con il costruttore e rendere tutti i campi come finali come indicato di seguito.

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);
}

possiamo usare la parola chiave const in un elenco .

const a = const [] - Una variabile a inizializzata in quanto constcontiene un elenco di constoggetti (ovvero, l'elenco deve contenere solo oggetti costanti di tempo di compilazione e immutabili). Quindi non siamo in grado di assegnare acon un altro elenco .

var a = const [] - Una variabile a inizializzata come varcontenente constoggetti di un elenco . Quindi possiamo assegnare un altro elenco alla variabilea .

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)];
}

finale:

parola chiave finale utilizzata anche per fare in modo che la variabile mantenga un valore costante . Una volta inizializzato, non è possibile modificare il valore.

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

Tutte le dichiarazioni menzionate di seguito sono accettabili.

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

È in grado di assegnare un valore di runtime .

// 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 variabile finale a livello di classe deve essere inizializzata nella stessa riga.

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

La variabile finale a livello di istanza deve essere inizializzata nella stessa riga o nell'inizializzazione del costruttore. Il valore verrà messo in memoria quando viene creato l'oggetto.

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);
}

Assegnare un elenco .

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

Estensione della risposta di @Meyi

  • la variabile finale può essere impostata una sola volta e viene inizializzata quando si accede (ad esempio dalla sezione di codice seguente se si utilizza il valore di biggestNumberOndicesolo allora il valore verrà inizializzato e la memoria verrà assegnata).
  • const è internamente di natura finale, ma la differenza principale è che la sua costante di tempo di compilazione che viene inizializzata durante la compilazione anche se non si utilizza il suo valore verrà inizializzata e occuperà spazio in memoria.

  • La variabile dalle classi può essere finale ma non costante e se si desidera una costante a livello di classe, renderla statica const.

Codice:

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
Penso che un modo migliore per porre la domanda sia quando preferire l'inizializzazione del runtime rispetto all'inizializzazione del tempo di compilazione ....
Faisal Naseer

e per questo puoi consultare la risposta di @Meyi e anche visitare il link dell'articolo dal suo post è meraviglioso :)
Faisal Naseer

2

Entrambi finale constimpediscono la riassegnazione di una variabile (simile a come finalfunziona in Java o come constfunziona in JavaScript).

La differenza ha a che fare con l'allocazione della memoria. La memoria è allocata per afinal variabile in fase di esecuzione e per una constvariabile in fase di compilazione. Il finalmodificatore dovrebbe essere il più comunemente usato, perché molte variabili di programma non avranno bisogno di memoria poiché la logica del programma non richiederà l'inizializzazione di esse. Con una constvariabile stai praticamente dicendo al computer: "Ehi, ho bisogno di memoria per questa variabile in anticipo perché so che ne avrò bisogno."

Pensarli in questo modo semplifica la comprensione delle differenze nel loro utilizzo sintattico. Principalmente che una finalvariabile può essere una variabile di istanza, ma a constdeve essere astatic variabile in una classe. Questo perché le variabili di istanza vengono create in fase di esecuzione e le constvariabili, per definizione, non lo sono. Pertanto, le constvariabili su una classe devono essere static, il che significa semplicemente che esiste una sola copia di quella variabile su una classe, indipendentemente dal fatto che quella classe sia istanziata.

Questo video lo scompone in modo abbastanza semplice: https://www.youtube.com/watch?v=9ZZL3iyf4Vk

Questo articolo approfondisce e spiega un'importantissima differenza semantica tra i due, ovvero finalmodifica le variabili econst modifica i valori, che si riduce essenzialmente alla possibilità di inizializzare solo constvalori che sono derivabili in fase di compilazione.

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


2

final e const in freccetta sono confusi al livello che riteniamo entrambi uguali.

Vediamo le loro differenze:

PS Ho incluso l'immagine anziché il testo in quanto non ho potuto tabulare facilmente le informazioni nel formato .md Stackoverflow.


1

Se vieni da C++allora constin Dartè constexprin C++e finalin Dartè constin C++.

Quanto sopra si applica solo ai tipi primitivi. Tuttavia negli Dartoggetti contrassegnatifinal sono modificabili in termini di membri.


2
Una specie di. Penso che potresti dirlo per tipi primitivi ma non per oggetti. constin C ++ viene quasi sempre usato per specificare che un oggetto non è mutabile attraverso un riferimento o un puntatore specifici. finalin Dart non impedisce che l'oggetto venga mutato attraverso quella variabile.
jamesdlin,

0

Non puoi inizializzare a constusando a final. Per esempio :

  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

Quando utilizzare quale parola chiave?

Un semplice esempio per entrambi: Usa final: se non sai quale sarà il suo valore al momento della compilazione. Ad esempio, quando è necessario ottenere dati da un'API, ciò accade quando si esegue il codice.

Usa const: se sei sicuro che un valore non verrà modificato durante l'esecuzione del codice. Ad esempio, quando dichiari una frase che rimane sempre la stessa.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.