web-dev-qa-db-ja.com

Dartの「const」キーワードと「final」キーワードの違いは何ですか?

Dartのconstキーワードとfinalキーワードの違いは何ですか?

71
Ishmal Ijaz

DartのWebサイトに投稿があり、かなりよく説明されています。

最終:

「final」は単一割り当てを意味します。最終変数またはフィールドmustには初期化子があります。値が割り当てられると、最終的な変数の値は変更できません。最終変更変数


定数:

「const」には、Dartではもう少し複雑で微妙な意味があります。 constはvaluesを変更します。 const [1、2、3]のようなコレクションを作成するとき、およびconst Point(2、3)のような(新しいのではなく)オブジェクトを構築するときに使用できます。ここで、constは、オブジェクトの深い状態全体がコンパイル時に完全に決定でき、オブジェクトがフリーズされ、完全に不変であることを意味します。

Constオブジェクトには、いくつかの興味深いプロパティと制限があります。

コンパイル時に計算できるデータから作成する必要があります。 constオブジェクトは、実行時に計算する必要があるものにはアクセスできません。 1 + 2は有効なconst式ですが、新しいDateTime.now()は無効です。

それらは深く、推移的に不変です。コレクションを含む最終フィールドがある場合、そのコレクションは変更可能です。 constコレクションがある場合、その中のすべても再帰的にconstである必要があります。

それらはcanonicalizedです。これは文字列のインターンのようなものです。任意のconst値に対して、const式が評価される回数に関係なく、1つのconstオブジェクトが作成され、再利用されます。


それで、これはどういう意味ですか?

定数:
値が実行時に計算された値(new DateTime.now()など)の場合、notを使用できますそれのためのconst。ただし、コンパイル時に値がわかっている場合(const a = 1;)、constではなくfinalを使用する必要があります。 constfinalには、他にも2つの大きな違いがあります。まず、constを使用している場合は、単にconstではなく、static constとして宣言する必要があります。次に、constコレクションがある場合、その中のすべてはconstにあります。 finalコレクションがある場合、その中のすべてはnotfinalです。

最終:
finalは、コンパイル時に値がわからない場合はconstよりも使用する必要があり、実行時に計算/取得されます。変更できないHTTP応答が必要な場合、データベースから何かを取得する場合、またはローカルファイルから読み取る場合は、finalを使用します。コンパイル時に不明なものはすべて、finalよりもconstである必要があります。


これらすべてのことから、constfinalの両方を再割り当てすることはできませんが、finalオブジェクト内のフィールドは、constまたはfinalでない限り、constとは異なり、再割り当てできます。

72
meyi

@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のもう1つの主な使用法は、object immutableを作成することです。クラスオブジェクトを不変にするには、以下で説明するようにコンストラクタでconstキーワードを使用にし、すべてのフィールドをfinalとしてにする必要があります。

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 a = const []-変数aconstオブジェクトのリストを含む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()];
24

@Meyiによる答えの拡張

  • final変数は1回しか設定できず、アクセス時に初期化されます(たとえば、以下のコードセクションからbiggestNumberOndiceの値を使用する場合のみ、値が初期化され、メモリが割り当てられます)。
  • constは本質的に内部的に最終的なものですが、主な違いは、値を使用しなくてもコンパイル時に初期化されるコンパイル時定数は初期化され、メモリ内のスペースを占有することです。

  • クラスの変数はfinalにすることもできますが、定数にすることはできません。クラスレベルで定数が必要な場合は、静的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;
}
15
Faisal Naseer

定数

値はcompile-timeconst birth = "2008/12/26"で認識されている必要があります。初期化後は変更できません


最後の

値はrun-timefinal birth = getBirthFromDB()で認識されている必要があります。初期化後は変更できません

4
Haroun Hajem

C++から来る場合、constDartC++constexprであり、finalDartC++constです。

上記はプリミティブ型にのみ適用されます。ただし、Dartとマークされたfinalオブジェクトでは、そのメンバーに関して可変です。

1
Moshe Rabaev