Jaka jest różnica między słowami kluczowymi „const” i „final” w Dart?


Odpowiedzi:


236

Na stronie darta jest post, który całkiem dobrze to wyjaśnia.

Finał:

„końcowe” oznacza przypisanie pojedyncze: końcowa zmienna lub pole musi mieć inicjator. Po przypisaniu wartości nie można zmienić końcowej wartości zmiennej. final modyfikuje zmienne .


Stała:

„const” ma znaczenie, które w Dart jest nieco bardziej złożone i subtelne. const modyfikuje wartości . Możesz go używać podczas tworzenia kolekcji, takich jak const [1, 2, 3], i podczas konstruowania obiektów (zamiast nowych), takich jak const Point (2, 3). Tutaj const oznacza, że ​​cały głęboki stan obiektu można określić całkowicie w czasie kompilacji i że obiekt zostanie zamrożony i całkowicie niezmienny.

Obiekty Const mają kilka interesujących właściwości i ograniczeń:

Muszą być tworzone na podstawie danych, które można obliczyć w czasie kompilacji. Obiekt const nie ma dostępu do niczego, co musiałbyś obliczyć w czasie wykonywania. 1 + 2 to prawidłowe wyrażenie const, ale new DateTime.now () już nie.

Są głęboko, przejściowo niezmienne. Jeśli masz ostatnie pole zawierające kolekcję, ta kolekcja nadal może być modyfikowalna. Jeśli masz kolekcję const, wszystko w niej musi być również const, rekurencyjnie.

Są kanonizowane . Jest to coś w rodzaju internowania ciągów: dla każdej podanej wartości stałej zostanie utworzony i ponownie użyty pojedynczy obiekt const, bez względu na to, ile razy wyrażenie (a) const jest oceniane.


Więc co to oznacza?

Const:
Jeżeli wartość masz jest obliczana w czasie wykonywania ( new DateTime.now()na przykład), można nie używać const dla niego. Jeśli jednak wartość jest znana w czasie kompilacji ( const a = 1;), należy użyć constover final. Istnieją 2 inne duże różnice między consti final. Po pierwsze, jeśli używasz const, musisz zadeklarować to jako, static consta nie tylko const. Po drugie, jeśli masz constkolekcję, wszystko w niej znajduje się const. Jeśli masz finalkolekcję, wszystko w niej nie jest final.

Final:
final powinno być użyte powyżej, constjeśli nie znasz wartości w czasie kompilacji i zostanie obliczona / pobrana w czasie wykonywania. Jeśli potrzebujesz odpowiedzi HTTP, której nie można zmienić, jeśli chcesz uzyskać coś z bazy danych lub jeśli chcesz odczytać z pliku lokalnego, użyj final. Wszystko, co nie jest znane w czasie kompilacji, powinno się finalskończyć const.


Biorąc to wszystko pod uwagę, zarówno consti finalnie można ich ponownie przypisać, ale pola w finalobiekcie, o ile nie są constlub final, można ponownie przypisać (w przeciwieństwie const).


3
Słowo kluczowe const jest używane do reprezentowania stałej czasu kompilacji. Zmienne zadeklarowane przy użyciu słowa kluczowego const są niejawnie ostateczne.
— Arun George

1
@Meyi, kiedy powinniśmy używać consti kiedy final? Czy znasz jakieś zastosowanie tego modyfikatora?
— CopsOnRoad

4
@CopsOnRoad możesz obejrzeć ten film na żywo Dart Const vs Final
— Lemuel Ogbunude

2
To ostatnie zdanie naprawdę dobrze to podsumowuje. Dziękuję za to.
— Yster,

Czy powinno nas obchodzić, że opcja const jest opcją? Czy wzrost wydajności jest naprawdę odczuwalny?
— CodeGrue

63

Konst

Wartość musi być znana w czasie kompilacji , const birthday = "2008/12/26"
nie można jej zmienić po zainicjowaniu.


Finał

Wartość musi być znana w czasie wykonywania , final birthday = getBirthDateFromDB()
nie można jej zmienić po zainicjowaniu.


10
Najłatwiejsze i najlepsze wyjaśnienie.
— Ankur Lahiry,

1
bardzo mi się podobał :)
— Faisal Naseer

43

Skonsolidowane odpowiedzi @Meyi i @ faisal-naseer oraz porównanie z niewielkim programowaniem.

const:

słowo kluczowe const używane do utworzenia zmiennej do przechowywania wartości stałej czasu kompilacji . Wartość stałej czasowej kompilacji to wartość, która będzie stała podczas kompilacji :-)

Na przykład 5jest stałą czasową kompilacji. Chociaż DateTime.now()nie jest to stała czasowa kompilacji. Ponieważ ta metoda zwróci czas, w którym linia jest wykonywana w czasie wykonywania. Więc nie możemy przypisać DateTime.now()do constzmiennej.

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

Powinien zostać zainicjowany w tym samym wierszu .

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;

Wszystkie poniższe stwierdzenia są dopuszczalne.

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

Zmienna const poziomu klasy powinna być zainicjowana jak poniżej.

Class A {
    static const a = 5;
}

Zmienna const na poziomie instancji nie jest możliwa .

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

Innym głównym zastosowaniem constjest uczynienie obiektu niezmiennym . Aby obiekt klasy stał się niezmienny, musimy użyć słowa kluczowego const z konstruktorem i nadać wszystkim polom ostateczne wartości, jak wspomniano poniżej.

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

możemy użyć słowa kluczowego const do listy .

const a = const [] - Zmienna a zainicjowana jako constzawierająca listę constobiektów (tj. lista powinna zawierać tylko stałą czasu kompilacji i niezmienne obiekty). Nie możemya więc przypisać innej listy .

var a = const [] - Zmienna a zainicjowana jako varzawierająca constobiekty listy . Więc możemy przypisać inną listę do zmienneja .

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

finał:

Słowo kluczowe final również służyło do ustawiania zmiennej jako stałej wartości . Po zainicjowaniu nie możemy zmienić wartości.

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

Wszystkie poniższe stwierdzenia są dopuszczalne.

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

Potrafi przypisać wartość wykonawczą .

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

Zmienna końcowa na poziomie klasy musi zostać zainicjowana w tym samym wierszu.

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

Zmienna końcowa na poziomie instancji musi zostać zainicjowana w tym samym wierszu lub w inicjalizacji konstruktora. Wartość zostanie zapisana w pamięci podczas tworzenia obiektu.

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

Przypisywanie listy .

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

Rozszerzenie odpowiedzi o @Meyi

  • końcowa zmienna może być ustawiona tylko raz i jest inicjowana po uzyskaniu do niej dostępu. (na przykład z sekcji kodu poniżej, jeśli użyjesz wartości biggestNumberOndicetylko wtedy wartość zostanie zainicjowana i zostanie przypisana pamięć).
  • const ma wewnętrznie ostateczny charakter, ale główną różnicą jest to, że jego stała czasu kompilacji, która jest inicjowana podczas kompilacji, nawet jeśli nie używasz jej wartości, zostanie zainicjowana i zajmie miejsce w pamięci.

  • Zmienna z klas może być ostateczna, ale nie stała, a jeśli chcesz mieć stałą na poziomie klasy, uczyń ją stałą statyczną.

Kod:

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
Myślę, że lepszym sposobem zadać pytanie jest, gdy wolą inicjalizacji Runtime inicjalizacji na czasie kompilacji ....
— Faisal Naseer

a do tego możesz sprawdzić odpowiedź @Meyi, a także odwiedzić link do artykułu z jego postu, jest cudowny :)
— Faisal Naseer

2

Oba finali constzapobiegają ponownemu przypisaniu zmiennej (podobnie jak finaldziała w Javie lub jak constdziała w JavaScript).

Różnica dotyczy sposobu alokacji pamięci. Pamięć jest przydzielana dla finalzmiennej w czasie wykonywania i dla constzmiennej w czasie kompilacji. finalModyfikator powinny być powszechnie stosowane, ponieważ wiele zmiennych, program nie wymaga żadnego pamięć ponieważ logika programu nie będzie wymagać, żeby zostać zainicjowany. Za pomocą constzmiennej w zasadzie mówisz komputerowi: „Hej, potrzebuję pamięci na tę zmienną z góry, ponieważ wiem, że będę jej potrzebować”.

Myślenie o nich w ten sposób ułatwia zrozumienie różnic w ich użyciu składniowym. Przede wszystkim finalzmienna może być zmienną instancji, ale constmusi być staticzmienną w klasie. Dzieje się tak, ponieważ zmienne instancji są tworzone w czasie wykonywania, a constzmienne - z definicji - nie. Tak więc constzmienne w klasie muszą być static, co oznacza po prostu, że pojedyncza kopia tej zmiennej istnieje w klasie, niezależnie od tego, czy ta klasa jest tworzona.

Ten film wyjaśnia to dość prosto: https://www.youtube.com/watch?v=9ZZL3iyf4Vk

Ten artykuł jest bardziej szczegółowy i wyjaśnia bardzo ważną różnicę semantyczną między nimi, tj. finalModyfikuje zmienne i constmodyfikuje wartości, co w istocie sprowadza się do możliwości inicjowania tylko constwartości, które można wyprowadzić w czasie kompilacji.

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


2

finalaw constrzutkach są mylące do tego stopnia, że ​​uważamy, że oba są takie same.

Zobaczmy ich różnice:

PS Zamiast tekstu dołączyłem obraz, ponieważ nie mogłem łatwo zestawić informacji w formacie Stackoverflow .md.


1

Jeżeli przyjeżdżasz z C++czym constsię Dartto constexprw C++i finalw Dartjest constw C++.

Powyższe dotyczy tylko typów pierwotnych. Jednak w Dartobiektach zaznaczone finalsą zmienne pod względem swoich członków.


2
Raczej. Myślę, że można to powiedzieć o typach prymitywnych, ale nie o obiektach. constw C ++ jest prawie zawsze używany do określenia, że ​​obiekt nie jest zmienny przez określone odwołanie lub wskaźnik. finalw Dart nie zapobiega mutacji obiektu przez tę zmienną.
— jamesdlin

0

Nie można zainicjować pliku constprzy użyciu pliku final. Na przykład :

  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

Kiedy używać którego słowa kluczowego?

Prosty przykład dla obu: Użyj final: Jeśli nie wiesz, jaka będzie jego wartość w czasie kompilacji. Na przykład, gdy trzeba pobrać dane z interfejsu API, dzieje się tak podczas uruchamiania kodu.

Użyj const: jeśli masz pewność, że wartość nie zostanie zmieniona podczas uruchamiania kodu. Na przykład, gdy deklarujesz zdanie, które zawsze pozostaje takie samo.

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.