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


172

ダートのconstfinalキーワードの違いは何ですか?


1
ここについていくつかの詳細はconststackoverflow.com/questions/51576209/...へと簡単なexplonationはfinal定数(finalキーワードで作成した後に再割り当てまたは割り当てることはできません)であり、あなたはそれを一度初期化する必要があります。
Blasanka、

回答:


235

ダートのウェブサイトに投稿があり、それはそれをかなりよく説明しています。

最後の:

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


定数:

「const」は、ダートではもう少し複雑で微妙な意味を持っています。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;)、constover を使用する必要がありますfinal。との間にはconst、他にも2つの大きな違いがありfinalます。まず、を使用している場合は、だけconstではstatic constなくとして宣言する必要がありますconst。次に、constコレクションがある場合、その中のすべてがにありconstます。あなたがfinalコレクションを持っている場合、その中のすべてはではありません final

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


以上のことをすべて説明すると、との両方constfinal再割り当てすることはできませんが、またはでfinalない限り、オブジェクトのフィールドを再割り当てできます(とは異なります)。constfinalconst


3
constキーワードは、コンパイル時の定数を表すために使用されます。constキーワードを使用して宣言された変数は、暗黙的にfinalです。
アルンジョージ

1
@Meyi、いつ使用する必要がconstありfinalますか?これらの修飾子のある種のユースケースを知っていますか?
CopsOnRoad 2018年

4
@CopsOnRoadでこのビデオをチェックできます。DartConst vs Final
Lemuel Ogbunude

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

のもう1つの主な用途は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 初期化されconstconstた変数(つまり、リストにはコンパイル時の定数と不変オブジェクトのみを含める必要があります)。そのため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キーワードは、変数に定数値保持させるためにも使用されます。初期化すると、値を変更できなくなります。

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による回答の拡張

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

  • クラスの変数はfinalにすることはできますが、定数にすることはできません。クラスレベルで定数が必要な場合は、静的な定数にします。

コード:

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

との両方が変数の再割り当てfinalconst防止します(finalJavaでの動作やconstJavaScriptでの動作と同様)。

違いは、メモリの割り当て方法に関係しています。メモリはfinal、実行時にconst変数に、コンパイル時に変数に割り当てられます。finalそれらを初期化するためのプログラムロジックは呼び出しませんので、多くのプログラム変数が任意のメモリを必要としないので、修飾子は、より一般的に、使用すべきです。const変数を使用すると、基本的にはコンピュータに、「ねえ、この変数が必要になることはわかっているので、この変数のためのメモリが必要です」と言っています。

このように考えると、構文の使い方の違いを理解しやすくなります。主に、final変数はインスタンス変数の場合がありますが、クラスの変数でconstなければなりませんstatic。これは、インスタンス変数は実行時に作成され、const変数(定義により)は作成されないためです。したがって、constクラスの変数はでなければなりませんstatic。つまり、そのクラスがインスタンス化されているかどうかに関係なく、その変数の単一のコピーがクラスに存在しているだけです。

このビデオはかなり単純にそれを分解します:https : //www.youtube.com/watch?v=9ZZL3iyf4Vk

この記事では、2つのfinal変数のconst変更と値の変更という非常に重要なセマンティックの違いについて詳しく説明します。つまり、基本的にはconst、コンパイル時に導出可能な値のみを初期化できるということです。

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


2

finalそして、constダーツに我々は彼らの両方が同じだと思うのレベルに混乱しています。

それらの違いを見てみましょう:

PS Stackoverflow .md形式で情報を簡単に表にできないため、テキストではなく画像を含めました。


1

あなたがから来ている場合はC++、その後constDartあるconstexprC++してfinalですで。DartconstC++

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


2
ちょっと。これはプリミティブ型では言えるが、オブジェクトではできないと思う。 constC ++では、ほとんどの場合、オブジェクトが特定の参照またはポインタを通じて変更できないことを指定するために使用されます。finalDartでは、その変数を介してオブジェクトが変更されるのを防ぐことはできません。
jamesdlin 2018年

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.