Яка різниця між ключовими словами "const" та "final" у Dart?


172

Яка різниця між constі finalключовим словом у Dart?


1
Ось деякі подробиці про const: stackoverflow.com/questions/51576209 / ... і простому explonation до finalпостійний (не може перепризначення або правонаступник після створення з остаточним ключовим словом) , і ви повинні ініціалізувати її один раз.
Бласанка

Відповіді:


236

На сайті дартса є публікація, і це досить добре пояснює.

Фінал:

"final" означає однозначне призначення: остаточна змінна або поле має мати ініціалізатор. Після призначення значення значення остаточної змінної не можна змінити. остаточний змінює змінні .


Const:

"const" має значення, яке є дещо складнішим і тонкішим у Dart. const змінює значення . Ви можете використовувати його під час створення колекцій, як const [1, 2, 3], і при побудові об'єктів (замість нових), таких як Const Point (2, 3). Тут const означає, що весь глибокий стан об'єкта може бути визначений повністю під час компіляції і що об'єкт буде застигнутим і повністю незмінним.

Об'єкти Const мають кілька цікавих властивостей та обмежень:

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

Вони глибоко, транзитивно незмінні. Якщо у вас є остаточне поле, що містить колекцію, ця збірка все ще може бути зміненою. Якщо у вас є колекція const, все в ній також повинно бути const, рекурсивно.

Вони канонізовані . Це щось на зразок інтернування інтерфейсу: для будь-якого заданого значення const один об'єкт const буде створений та повторно використаний незалежно від того, скільки разів виражаються вирази const.


Отже, що це означає?

Const:
Якщо значення, яке ви маєте, обчислюється під час виконання ( new DateTime.now()наприклад), ви не можете використовувати const для нього. Однак, якщо значення відомо під час компіляції ( const a = 1;), тоді вам слід скористатися constнад final. Є ще 2 великі відмінності між constта final. По-перше, якщо ви використовуєте const, ви повинні оголосити це як static constпросто, а не просто const. По-друге, якщо у вас є constколекція, все, що знаходиться всередині цього є const. Якщо у вас є finalколекція, все всередині цього немає final .

Остаточний: його
final слід використовувати, constякщо ви не знаєте значення під час компіляції, і воно буде обчислено / схоплено під час виконання. Якщо ви хочете відповідь HTTP, яку неможливо змінити, якщо ви хочете отримати щось із бази даних, або якщо ви хочете прочитати з локального файлу, використовуйте final. Все, що не відомо на час компіляції, має finalзакінчитися const.


Незважаючи на все сказане, обидва constі finalне можуть бути перепризначені, але поля в finalоб'єкті, доки їх немає constабо finalможуть бути перепризначені (на відміну від const).


3
Ключове слово const використовується для представлення константи часу компіляції. Змінні, оголошені за допомогою ключового слова const, неявно остаточні.
Арун Джордж

1
@Meyi, коли нам використовувати constі коли final? Чи знаєте ви якийсь варіант використання цього модифікатора?
CopsOnRoad

4
@CopsOnRoad ви можете подивитися це відео з " Дарт Конст" проти "Фіналу"
Лемуель Огбундуе

2
Це останнє речення справді так добре підсумовує його. Дякую за це.
Yster

Чи нам навіть байдуже, що const - це варіант? Чи справді відчутний приріст продуктивності?
CodeGrue

63

Конст

Значення повинно бути відоме під час компіляції , його const birthday = "2008/12/26"
неможливо змінити після ініціалізації.


Фінал

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


10
Найпростіше і найкраще пояснення.
Ankur Lahiry

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;

Змінна const рівня класу повинна бути ініціалізована як нижче.

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 Ініціалізованаvarconst змінна , яка містить об'єкти списку . Таким чином ми можемо призначити інший список змінній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 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

  • остаточну змінну можна встановити лише один раз, і вона ініціалізується при доступі до неї (наприклад, з розділу коду нижче, якщо ви використовуєте значення biggestNumberOndiceлише тоді, значення буде ініціалізовано і буде призначено пам'ять).
  • const є внутрішньо остаточним за своєю суттю, але головна відмінність полягає в тому, що його константа часу компіляції, яка ініціалізується під час компіляції, навіть якщо ви не використовуєте її значення, вона буде ініціалізована і займе місце в пам'яті.

  • Змінна від класів може бути остаточною, але не постійною, і якщо ви хочете константа на рівні класу, зробіть це статичним 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


2

finalі constв дартсі плутають рівень, який ми думаємо, що вони обоє однакові.

Подивимось їх відмінності:

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


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

0

Коли використовувати яке ключове слово?

Простий приклад для обох: Використовуйте final: Якщо ви не знаєте, яке значення буде в час компіляції. Наприклад, коли вам потрібно буде отримати дані з API, це відбувається під час запуску вашого коду.

Використовуйте const: Якщо ви впевнені, що значення не буде змінено під час запуску коду. Наприклад, коли ви оголошуєте речення, яке завжди залишається однаковим.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.