В чем разница между «const» и «final» ключевыми словами в Dart?

173

В чем разница между constи finalключевым словом в Дарте?

Ишмаль Ияз
источник
1
Вот некоторые подробности о const: stackoverflow.com/questions/51576209/… и простое объяснение к finalявляется постоянным (не может переназначаться или назначаться после создания с ключевым словом final), и вам придется инициализировать его один раз.
Бласанка

Ответы:

237

На сайте дартс есть пост, который довольно хорошо объясняет.

Финал:

«final» означает одиночное присваивание: конечная переменная или поле должны иметь инициализатор. После присвоения значения значение окончательной переменной не может быть изменено. Конечные модифицирует переменные .


Const:

«const» имеет значение, которое немного сложнее и тоньше в Dart. const изменяет значения . Вы можете использовать его при создании коллекций, таких как const [1, 2, 3], и при создании объектов (вместо новых), таких как const Point (2, 3). Здесь const означает, что все глубокое состояние объекта может быть полностью определено во время компиляции и что объект будет заморожен и полностью неизменен.

У объектов Const есть пара интересных свойств и ограничений:

Они должны быть созданы из данных, которые могут быть рассчитаны во время компиляции. Константный объект не имеет доступа ни к чему, что вам нужно будет вычислить во время выполнения. 1 + 2 является допустимым выражением const, но новый DateTime.now () - нет.

Они глубоко, транзитивно неизменны. Если у вас есть последнее поле, содержащее коллекцию, эта коллекция все еще может быть изменяемой. Если у вас есть коллекция const, все в ней также должно быть const, рекурсивно.

Они канонизированы . Это похоже на интернирование строк: для любого заданного значения const будет создан и повторно использован один объект const независимо от того, сколько раз вычислено выражение (выражения) const.


Итак, что это значит?

Const:
Если у вас есть значение, вычисленное во время выполнения ( new DateTime.now()например), вы не можете использовать const для него. Однако, если значение известно во время компиляции ( const a = 1;), вам следует использовать constover final. Есть 2 других больших различия между constи final. Во-первых, если вы используете const, вы должны объявить это, static constа не просто const. Во-вторых, если у вас есть constколлекция, все внутри нее находится внутри const. Если у вас есть finalколлекция, все внутри этого нет final .

Final:
final следует использовать повторно, constесли вы не знаете значение во время компиляции, и оно будет вычислено / получено во время выполнения. Если вам нужен HTTP-ответ, который нельзя изменить, если вы хотите получить что-то из базы данных или если вы хотите читать из локального файла, используйте final. Все, что не известно во время компиляции, должно быть finalзакончено const.


С учетом всего вышесказанного оба constи finalне могут быть переназначены, но поля в finalобъекте, если их нет constили finalмогут быть переназначены (в отличие от const).

meyi
источник
3
Ключевое слово const используется для представления константы времени компиляции. Переменные, объявленные с использованием ключевого слова const, неявно являются окончательными.
Арун Джордж
1
@Meyi, когда мы должны использовать constи когда final? Знаете ли вы какой-то вариант использования этих модификаторов?
CopsOnRoad
4
@CopsOnRoad вы можете проверить это видео Дарт Конст против Финала
Лемуэль Огбунуде
2
Последнее предложение действительно так хорошо подводит итог. Спасибо за это.
Yster
Должны ли мы вообще заботиться о том, чтобы const был вариантом? Действительно ли прирост производительности ощутим?
CodeGrue
64

Const

Значение должно быть известно во время компиляции , const birthday = "2008/12/26"
не может быть изменено после инициализации.


окончательный

Значение должно быть известно во время выполнения , final birthday = getBirthDateFromDB()
не может быть изменено после инициализации.

Харун Хайем
источник
11
Самое простое и лучшее объяснение.
Анкур Лахири
1
любил этот :)
Faisal Naseer
43

Консолидированные ответы @Meyi и @ faisal-naseer и сравнение с небольшим программированием.

Const:

Ключевое слово const используется для создания переменной для хранения значения времени компиляции . Значение постоянной времени компиляции - это значение, которое будет постоянным при компиляции :-)

Например 5, это постоянная времени компиляции. Пока DateTime.now()что не компилируем постоянную времени. Потому что этот метод будет возвращать время выполнения строки во время выполнения. Таким образом , мы не можем присвоить DateTime.now()к constпеременной.

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

Должен быть инициализирован в той же строке .

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;

Все утверждения, указанные ниже, являются приемлемыми.

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

Константная переменная уровня класса должна быть инициализирована, как показано ниже.

Class A {
    static const a = 5;
}

Переменная const уровня экземпляра невозможна .

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

Другое основное использование constиспользуется, чтобы сделать объект неизменным . Чтобы сделать объект класса неизменным, нам нужно использовать ключевое слово const с конструктором и сделать все поля окончательными, как указано ниже.

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

мы можем использовать ключевое слово const для списка .

const a = const [] - переменная, a инициализированная как constсодержащая список constобъектов (т. е. список должен содержать только постоянную времени компиляции и неизменные объекты). Поэтому мы не можем назначить aдругой список .

var a = const [] - переменная, a инициализированная как varсодержащая список constобъектов . Таким образом, мы можем назначить другой список переменнойa .

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 также используется для того, чтобы переменная содержала постоянное значение . После инициализации мы не можем изменить значение.

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

Все утверждения, указанные ниже, являются приемлемыми.

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

Может в состоянии назначить значение времени выполнения .

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

Последняя переменная уровня класса должна быть инициализирована в той же строке.

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

Последняя переменная уровня экземпляра должна быть инициализирована в той же строке или в инициализаторе конструктора. Значение будет занесено в память при создании объекта.

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

Назначение списка .

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

Расширяя ответ @Meyi

  • Последняя переменная может быть установлена ​​только один раз, и она инициализируется при обращении к ней (например, из приведенного ниже раздела кода, если вы используете значение biggestNumberOndiceonly, значение будет инициализировано и будет выделена память).
  • const внутренне финален по своей природе, но основное отличие состоит в том, что его постоянная времени компиляции, которая инициализируется во время компиляции, даже если вы не используете ее значение, будет инициализирована и займет место в памяти.

  • Переменная из классов может быть конечной, но не константной, и если вы хотите, чтобы константа на уровне класса делала ее статической константой.

Код:

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
Я думаю, что лучший способ задать вопрос - когда предпочесть инициализацию во время выполнения над инициализацией во время компиляции ...
Faisal Naseer
и для этого вы можете проконсультироваться с ответом @Meyi, а также посетить ссылку статьи из его поста, это замечательно :)
Faisal Naseer
2

И то finalи другое constпредотвращает переназначение переменной (аналогично тому, как finalработает в Java или как constработает в JavaScript).

Разница связана с тем, как распределяется память. Память выделяется для finalпеременной во время выполнения и для constпеременной во время компиляции. finalМодификатор должен быть более широко используется, потому что многие программные переменные не нужна память , так как логика программы не будет требовать их инициализации. С constпеременной вы в основном говорите компьютеру: «Эй, мне нужна память для этой переменной, потому что я знаю, что она мне понадобится».

Думая о них таким образом, легче понять различия в их синтаксическом использовании. Главным образом, finalпеременная может быть переменной экземпляра, но constдолжна быть staticпеременной класса. Это потому, что переменные экземпляра создаются во время выполнения, а constпеременные - по определению - нет. Таким образом, constпеременные в классе должны быть static, что просто означает, что в классе существует единственная копия этой переменной, независимо от того, создан ли этот класс.

Это видео довольно просто: https://www.youtube.com/watch?v=9ZZL3iyf4Vk

Эта статья углубляется и объясняет очень важное семантическое различие между ними, то есть finalизменяет переменные и constизменяет значения, что сводится к возможности инициализировать только constзначения, которые выводятся во время компиляции.

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

holding_the_center_down
источник
2

final и const в дротике путают до уровня, мы думаем, что они оба одинаковы.

Давайте посмотрим на их различия:

PS Я включил изображение вместо текста, так как я не мог легко табулировать информацию в формате Stackoverflow .md.

erluxman
источник
1

Если вы приехали из, C++то constв Dartэто constexprв C++и finalв Dartэто constв C++.

Вышесказанное относится только к примитивным типам. Однако в Dartотмеченных объектах finalизменчивы с точки зрения его членов.

Моше Рабаев
источник
2
Вроде, как бы, что-то вроде. Я думаю, что вы могли бы сказать это для примитивных типов, но не для объектов. constв C ++ почти всегда используется для указания того, что объект не является изменяемым через конкретную ссылку или указатель. finalв Dart не предотвращает мутирование объекта через эту переменную.
Джеймсдлин
0

Вы не можете инициализировать constиспользование final. Например :

  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»
источник
0

Когда использовать какое ключевое слово?

Простой пример для обоих: Используйте final: если вы не знаете, какое значение будет иметь значение во время компиляции. Например, когда вам может потребоваться получить данные из API, это происходит при запуске вашего кода.

Используйте const: если вы уверены, что значение не будет изменено при запуске вашего кода. Например, когда вы объявляете предложение, которое всегда остается неизменным.

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

Фейсал Ахмед
источник