Qual é a diferença entre as palavras-chave "const" e "final" no Dart?

172

Qual é a diferença entre conste finalkeyword no Dart?

Ishmal Ijaz
fonte
1
Aqui estão alguns detalhes sobre const: stackoverflow.com/questions/51576209/… e a explicação simples para finalé constante (não é possível reatribuir ou atribuir uma vez criada com a palavra-chave final) e você deve inicializá-la uma vez.
Blasanka

Respostas:

235

Há uma postagem no site da dardo e explica muito bem.

Final:

"final" significa atribuição única: uma variável ou campo final deve ter um inicializador. Depois de atribuído um valor, o valor de uma variável final não pode ser alterado. final modifica variáveis .


Const:

"const" tem um significado um pouco mais complexo e sutil no Dart. const modifica valores . Você pode usá-lo ao criar coleções, como const [1, 2, 3], e ao construir objetos (em vez de novos) como const Point (2, 3). Aqui, const significa que todo o estado profundo do objeto pode ser determinado inteiramente em tempo de compilação e que o objeto será congelado e completamente imutável.

Os objetos Const têm algumas propriedades e restrições interessantes:

Eles devem ser criados a partir de dados que podem ser calculados em tempo de compilação. Um objeto const não tem acesso a nada que você precisaria calcular em tempo de execução. 1 + 2 é uma expressão const válida, mas o novo DateTime.now () não é.

Eles são profundamente, transitivamente imutáveis. Se você tiver um campo final contendo uma coleção, essa coleção ainda poderá ser mutável. Se você tem uma coleção const, tudo nela também deve ser const, recursivamente.

Eles são canonizados . É como uma cadeia interna de strings: para qualquer valor const constante, um único objeto const será criado e reutilizado, não importando quantas vezes as expressões const sejam avaliadas.


Então o que isso quer dizer?

Const:
se o valor que você possui é calculado em tempo de execução ( new DateTime.now()por exemplo), não é possível usar uma const para ele. No entanto, se o valor for conhecido em tempo de compilação ( const a = 1;), você deverá usar constover final. Existem outras 2 grandes diferenças entre conste final. Em primeiro lugar, se você estiver usando const, você deve declará-lo como algo que static constnão apenas const. Em segundo lugar, se você tiver uma constcoleção, tudo dentro dela está incluído const. Se você tem uma finalcoleção, tudo dentro dela não é final.

Final:
final deve ser usado novamente constse você não souber o valor no tempo de compilação e será calculado / obtido no tempo de execução. Se você deseja uma resposta HTTP que não possa ser alterada, se deseja obter algo de um banco de dados ou se deseja ler de um arquivo local, use final. Qualquer coisa que não seja conhecida no momento da compilação deve finalterminar const.


Com tudo isso dito, ambos conste finalnão podem ser reatribuídos, mas os campos em um finalobjeto, desde que não sejam constou finalpossam ser reatribuídos (ao contrário const).

meyi
fonte
3
A palavra-chave const é usada para representar uma constante em tempo de compilação. Variáveis ​​declaradas usando a palavra-chave const são implicitamente finais.
Arun George
1
@Meyi, quando devemos usar conste quando final? Você conhece algum tipo de caso de uso para esse modificador?
CopsOnRoad
4
@CopsOnRoad, você pode conferir este vídeo Dart Const vs Final
Lemuel Ogbunude
2
Essa última frase realmente resume muito bem. Obrigado por isso.
Yster
Deveríamos nos importar que const é uma opção? O ganho de desempenho é realmente perceptível?
CodeGrue
63

Const

O valor deve ser conhecido em tempo de compilação ,const birthday = "2008/12/26"
Não pode ser alterado após a inicialização.


Final

O valor deve ser conhecido no tempo de execução . final birthday = getBirthDateFromDB()
Não pode ser alterado após a inicialização.

Haroun Hajem
fonte
10
A explicação mais fácil e melhor.
Ankur Lahiry 21/03
1
adorei esse :)
Faisal Naseer 04/07
43

Respostas consolidadas @Meyi e @ faisal-naseer e Comparando com pouca programação.

const:

palavra-chave const usada para criar uma variável para armazenar um valor constante de tempo de compilação . O valor constante do tempo de compilação é um valor que será constante durante a compilação :-)

Por exemplo, 5é uma constante de tempo de compilação. Enquanto DateTime.now()que não é tempo de compilação constante. Porque esse método retornará o horário em que a linha está sendo executada em tempo de execução. Portanto, não podemos atribuir a DateTime.now()uma constvariável.

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

Deve ser inicializado na mesma linha .

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;

Todas as declarações mencionadas abaixo são aceitáveis.

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

A variável const de nível de classe deve ser inicializada como abaixo.

Class A {
    static const a = 5;
}

A variável const no nível da instância não é possível .

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

O outro uso principal consté usado para tornar o objeto imutável . Para tornar um objeto de classe imutável, precisamos usar a palavra-chave const com o construtor e tornar todos os campos finais, como mencionado abaixo.

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

podemos usar a palavra-chave const para uma lista .

const a = const [] - Uma variável a inicializada como a constque contém uma lista de constobjetos (ou seja, a lista deve conter apenas objetos constantes e imutáveis ​​em tempo de compilação). Portanto , não podemos atribuir aa outra lista .

var a = const [] - Uma variável a inicializada como a varque contém os constobjetos de uma lista . Assim , podemos atribuir outra lista à variávela .

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:

A palavra-chave final também é usada para fazer com que a variável mantenha um valor constante . Uma vez inicializado, não podemos alterar o valor.

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

Todas as declarações mencionadas abaixo são aceitáveis.

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

Consegue atribuir um valor de tempo de execução .

// 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;

A variável final no nível da classe deve ser inicializada na mesma linha.

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

A variável final no nível da instância deve ser inicializada na mesma linha ou na inicialização do construtor. O valor será colocado na memória quando o objeto for criado.

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

Atribuindo uma lista .

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()];
Mahendran Sakkarai
fonte
20

Estendendo a resposta por @Meyi

  • A variável final pode ser definida apenas uma vez e é inicializada quando acessada (por exemplo, na seção de código abaixo, se você usar o valor de biggestNumberOndicesomente então, o valor será inicializado e a memória será atribuída).
  • const é internamente final por natureza, mas a principal diferença é que sua constante de tempo de compilação, que é inicializada durante a compilação, mesmo que você não use seu valor, ela será inicializada e ocupará espaço na memória.

  • A variável das classes pode ser final, mas não constante, e se você quiser uma constante no nível da classe, torne-a estática.

Código:

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;
}
Faisal Naseer
fonte
2
Eu acho que a melhor maneira de fazer a pergunta é quando a preferir a inicialização de tempo de execução de inicialização sobre compilação tempo ....
Faisal Naseer
e para isso você pode consultar resposta @Meyi e também não visitar o link do artigo de seu posto o seu maravilhoso :)
Faisal Naseer
2

Ambos finale constevitar uma variável de ser transferido (semelhante à forma como finalfunciona em Java ou comoconst trabalhos em JavaScript).

A diferença tem a ver com a maneira como a memória é alocada. A memória é alocada para uma finalvariável em tempo de execução e para uma constvariável em tempo de compilação. O finalmodificador deve ser o mais comumente usado, porque muitas variáveis ​​de programa não precisam de memória, pois a lógica do programa não exige que sejam inicializadas. Com umconst variável, você basicamente diz ao computador: "Ei, preciso de memória para essa variável logo porque sei que vou precisar".

Pensar nelas dessa maneira facilita a compreensão das diferenças em seu uso sintático. Principalmente que uma finalvariável pode ser uma variável de instância, mas constdeve ser uma staticvariável em uma classe. Isso ocorre porque as variáveis ​​de instância são criadas em tempo de execução e as constvariáveis ​​- por definição - não são. Assim, constvariáveis ​​em uma classe devem serstatic , o que significa simplesmente que uma única cópia dessa variável existe em uma classe, independentemente de essa classe ser instanciada.

Este vídeo divide-o de maneira bastante simples: https://www.youtube.com/watch?v=9ZZL3iyf4Vk

Este artigo aborda mais profundamente e explica uma diferença semântica muito importante entre os dois, ou seja, finalmodifica variáveis ​​e constmodifica valores, que basicamente se resumem a apenas ser capaz de inicializar constvalores deriváveis ​​em tempo de compilação.

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

holding_the_center_down
fonte
2

finale constno dardo são confusos ao nível que pensamos que os dois são iguais.

Vamos ver suas diferenças:

PS: Incluí imagem em vez de texto, pois não consigo tabular as informações no formato Stackoverflow .md facilmente.

erluxman
fonte
1

Se você está vindo C++em seguida, constem Darté constexprem C++e finalem Darté constno C++.

O acima se aplica apenas aos tipos primitivos. No entanto, nos Dartobjetos marcados finalsão mutáveis ​​em termos de seus membros.

Moshe Rabaev
fonte
2
Tipo de. Eu acho que você poderia dizer isso para tipos primitivos, mas não para objetos. constquase sempre é usado em C ++ para especificar que um objeto não é mutável por meio de uma referência ou ponteiro específico. finalno Dart não impede que o objeto seja alterado por essa variável.
jamesdlin
0

Você não pode inicializar um constusando a final. Por exemplo :

  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
Jéwôm '
fonte
0

Quando usar qual palavra-chave?

Um exemplo simples para ambos: Use final: se você não souber qual será o valor no momento da compilação. Por exemplo, quando você pode precisar obter dados de uma API, isso acontece ao executar seu código.

Use const: se você tem certeza de que um valor não será alterado ao executar seu código. Por exemplo, quando você declara uma frase que sempre permanece a mesma.

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

Faisal Ahmed
fonte