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.

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.