Sự khác biệt giữa các từ khóa của nhóm const const và khác nhau trong trò chơi Dart là gì?


172

Sự khác biệt giữa constfinaltừ khóa trong Dart là gì?


1
Dưới đây là một số chi tiết về const: stackoverflow.com/questions/51576209/ và cách giải thích đơn giản finallà không đổi (không thể gán lại hoặc gán một khi được tạo bằng từ khóa cuối cùng) và bạn phải khởi tạo nó một lần.
Blasanka

Câu trả lời:


235

Có một bài đăng trên trang web của phi tiêu và nó giải thích nó khá tốt.

Sau cùng:

"Final" có nghĩa là gán đơn: một biến hoặc trường cuối cùng phải có bộ khởi tạo. Khi đã gán một giá trị, giá trị của biến cuối cùng không thể thay đổi. cuối cùng sửa đổi các biến .


Hăng sô:

"const" có nghĩa là phức tạp và tinh tế hơn một chút trong Dart. const sửa đổi các giá trị . Bạn có thể sử dụng nó khi tạo các bộ sưu tập, như const [1, 2, 3] và khi xây dựng các đối tượng (thay vì mới) như const Point (2, 3). Ở đây, const có nghĩa là toàn bộ trạng thái sâu của đối tượng có thể được xác định hoàn toàn tại thời gian biên dịch và đối tượng sẽ bị đóng băng và hoàn toàn bất biến.

Các đối tượng Const có một vài thuộc tính và hạn chế thú vị:

Chúng phải được tạo từ dữ liệu có thể được tính toán tại thời điểm biên dịch. Một đối tượng const không có quyền truy cập vào bất cứ điều gì bạn cần tính toán khi chạy. 1 + 2 là biểu thức const hợp lệ, nhưng DateTime.now () mới thì không.

Họ sâu sắc, bất di bất dịch. Nếu bạn có một trường cuối cùng chứa một bộ sưu tập, bộ sưu tập đó vẫn có thể thay đổi. Nếu bạn có một bộ sưu tập const, mọi thứ trong đó cũng phải là const, đệ quy.

Họ được hợp quy hóa . Đây là loại giống như thực hiện chuỗi: đối với bất kỳ giá trị const đã cho nào, một đối tượng const duy nhất sẽ được tạo và sử dụng lại bất kể số lần biểu thức const được đánh giá.


Vì vậy, điều này có nghĩa là gì?

Const:
Nếu giá trị bạn có được tính trong thời gian chạy ( new DateTime.now()ví dụ), bạn không thể sử dụng const cho nó. Tuy nhiên, nếu giá trị được biết tại thời gian biên dịch ( const a = 1;), thì bạn nên sử dụng consthơn final. Có 2 sự khác biệt lớn khác giữa constfinal. Đầu tiên, nếu bạn đang sử dụng const, bạn phải khai báo nó static constthay vì chỉ const. Thứ hai, nếu bạn có một constbộ sưu tập, tất cả mọi thứ bên trong đó đều nằm trong đó const. Nếu bạn có một finalbộ sưu tập, mọi thứ bên trong đó không phảifinal.

Cuối cùng:
final nên được sử dụng constnếu bạn không biết giá trị tại thời gian biên dịch và nó sẽ được tính / lấy khi chạy. Nếu bạn muốn phản hồi HTTP không thể thay đổi, nếu bạn muốn lấy thứ gì đó từ cơ sở dữ liệu hoặc nếu bạn muốn đọc từ tệp cục bộ, hãy sử dụng final. Bất cứ điều gì không được biết đến vào thời gian biên dịch sẽ finalkết thúc const.


Với tất cả những gì đã nói, cả hai constfinalkhông thể được chỉ định lại, nhưng các trường trong một finalđối tượng, miễn là chúng không consthoặc final, có thể được chỉ định lại (không giống như const).


3
Từ khóa const được sử dụng để biểu diễn hằng số thời gian biên dịch. Các biến được khai báo sử dụng từ khóa const là hoàn toàn cuối cùng.
Arun George

1
@Meyi, khi nào chúng ta nên sử dụng constvà khi finalnào? Bạn có biết một số trường hợp sử dụng cho các sửa đổi?
CopsOnRoad


2
Câu cuối cùng đó thực sự tóm gọn nó rất tốt. Cảm ơn vì điều đó.
Yster

Chúng ta thậm chí có nên quan tâm rằng const là một lựa chọn? Là hiệu suất đạt được thực sự cảm nhận?
CodeGrue

63

hăng sô

Giá trị phải được biết tại thời gian biên dịch , const birthday = "2008/12/26"
Không thể thay đổi sau khi khởi tạo.


Sau cùng

Giá trị phải được biết vào thời gian chạy , final birthday = getBirthDateFromDB()
Không thể thay đổi sau khi khởi tạo.


10
Giải thích dễ nhất và tốt nhất.
Ankur Lahiry

1
yêu cái này :)
Faisal Naseer

43

Hợp nhất các câu trả lời @Meyi và @ faisal-naseer và So sánh với lập trình nhỏ.

hăng sô:

const từ khóa được sử dụng để tạo một biến để lưu trữ giá trị hằng số thời gian biên dịch . Biên dịch giá trị hằng số thời gian là một giá trị sẽ không đổi trong khi biên dịch :-)

Ví dụ 5là hằng số thời gian biên dịch. Trong khi DateTime.now()đó không phải là biên dịch thời gian không đổi. Bởi vì phương thức này sẽ trả về thời gian khi dòng đang được thực thi trong thời gian chạy. Vì vậy, chúng ta không thể gán biến DateTime.now()cho một constbiến.

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

Nên được khởi tạo ở cùng một dòng .

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;

Tất cả các tuyên bố dưới đây được chấp nhận.

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

Biến lớp cấp const nên được khởi tạo như dưới đây.

Class A {
    static const a = 5;
}

Biến cấp độ const là không thể .

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

Việc sử dụng chính khác constđược sử dụng để làm cho đối tượng bất biến . Để làm cho một đối tượng lớp bất biến, chúng ta cần sử dụng từ khóa const với hàm tạo và tạo tất cả các trường là cuối cùng như được đề cập dưới đây.

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

chúng ta có thể sử dụng từ khóa const vào danh sách .

const a = const [] - Một biến được a khởi tạo như constchứa danh sách các constđối tượng (nghĩa là Danh sách chỉ chứa các đối tượng hằng số thời gian và bất biến). Vì vậy, chúng tôi không thể chỉ định avới một danh sách khác .

var a = const [] - Một biến được a khởi tạo như varchứa một constđối tượng danh sách . Vì vậy, chúng ta có thể gán một danh sách khác cho biếna .

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

sau cùng:

từ khóa cuối cùng cũng được sử dụng để làm cho biến giữ giá trị không đổi . Sau khi khởi tạo, chúng tôi không thể thay đổi giá trị.

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

Tất cả các tuyên bố dưới đây được chấp nhận.

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

Có thể gán giá trị thời gian chạy .

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

Biến cuối cùng của cấp lớp phải được khởi tạo trong cùng một dòng.

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

Biến cuối cùng của cấp độ sơ thẩm phải được khởi tạo trong cùng một dòng hoặc trong khởi tạo hàm tạo. Giá trị sẽ được đưa vào bộ nhớ khi đối tượng được tạo.

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

Chỉ định một danh sách .

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

Mở rộng câu trả lời của @Meyi

  • biến cuối cùng chỉ có thể được đặt một lần và nó được khởi tạo khi được truy cập. (ví dụ từ phần mã bên dưới nếu bạn chỉ sử dụng giá trị biggestNumberOndicethì giá trị sẽ được khởi tạo và bộ nhớ sẽ được chỉ định).
  • const là bản chất cuối cùng về bản chất nhưng sự khác biệt chính là hằng số thời gian biên dịch của nó được khởi tạo trong quá trình biên dịch ngay cả khi bạn không sử dụng giá trị của nó, nó sẽ được khởi tạo và sẽ chiếm dung lượng trong bộ nhớ.

  • Biến từ các lớp có thể là cuối cùng nhưng không phải là hằng số và nếu bạn muốn một hằng số ở cấp độ lớp, hãy biến nó thành hằng tĩnh.

Mã số:

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
Tôi nghĩ một cách tốt hơn để đặt câu hỏi là khi nào nên thích khởi tạo thời gian chạy hơn khởi tạo thời gian biên dịch ....
Faisal Naseer

và để làm điều đó, bạn có thể tham khảo câu trả lời của @Meyi và cũng có thể truy cập vào liên kết của bài viết từ bài đăng của anh ấy thật tuyệt vời :)
Faisal Naseer

2

Cả hai finalconstngăn chặn một biến được gán lại (tương tự như cách finalhoạt động trong Java hoặc cách consthoạt động trong JavaScript).

Sự khác biệt có liên quan đến cách phân bổ bộ nhớ. Bộ nhớ được phân bổ cho một finalbiến trong thời gian chạy và cho một constbiến tại thời gian biên dịch. Công cụ finalsửa đổi nên được sử dụng phổ biến hơn, bởi vì nhiều biến chương trình sẽ không cần bất kỳ bộ nhớ nào vì logic chương trình sẽ không yêu cầu chúng được khởi tạo. Với một constbiến số về cơ bản bạn đang nói với máy tính, "Này, tôi cần bộ nhớ cho biến này trước vì tôi biết tôi sẽ cần nó."

Suy nghĩ về chúng theo cách này giúp dễ hiểu hơn về sự khác biệt trong cách sử dụng cú pháp của chúng. Chủ yếu là một finalbiến có thể là một biến thể hiện, nhưng constphải là một staticbiến trên một lớp. Điều này là do các biến thể hiện được tạo ra trong thời gian chạy và constcác biến - theo định nghĩa - thì không. Do đó, constcác biến trên một lớp phải là static, điều đó có nghĩa đơn giản là một bản sao duy nhất của biến đó tồn tại trên một lớp, bất kể lớp đó có được khởi tạo hay không.

Video này phá vỡ nó khá đơn giản: https://www.youtube.com/watch?v=9ZZL3iyf4Vk

Bài viết này đi sâu hơn và giải thích một sự khác biệt ngữ nghĩa rất quan trọng giữa hai yếu tố này, tức là finalsửa đổi các biến và constsửa đổi các giá trị, về cơ bản chỉ có thể khởi tạo constcác giá trị có thể phát sinh được trong thời gian biên dịch.

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


2

finalconsttrong phi tiêu là khó hiểu đến mức chúng tôi nghĩ rằng cả hai đều giống nhau.

Hãy xem sự khác biệt của họ:

PS Tôi đã bao gồm hình ảnh thay vì văn bản vì tôi không thể lập bảng thông tin ở định dạng Stackoverflow .md một cách dễ dàng.


1

Nếu bạn đang đến từ C++sau đó consttrong Dartconstexprtrong C++finaltrong Dartconsttrong C++.

Những điều trên chỉ áp dụng cho các loại nguyên thủy. Tuy nhiên, trong Dartcác đối tượng được đánh dấu finallà có thể thay đổi về các thành viên của nó.


2
Sắp xếp Tôi nghĩ bạn có thể nói điều này cho các kiểu nguyên thủy nhưng không phải cho các đối tượng. consttrong C ++ hầu như luôn được sử dụng để xác định rằng một đối tượng không thể thay đổi thông qua một tham chiếu hoặc con trỏ cụ thể. finaltrong Dart không ngăn đối tượng bị đột biến thông qua biến đó.
jamesdlin

0

Bạn không thể khởi tạo constsử dụng a final. Ví dụ :

  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

Khi nào sử dụng từ khóa nào?

Một ví dụ đơn giản cho cả hai: Sử dụng cuối cùng: Nếu bạn không biết giá trị của nó sẽ là gì vào thời gian biên dịch. Ví dụ: khi bạn có thể cần lấy dữ liệu từ API, điều này xảy ra khi chạy mã của bạn.

Sử dụng const: Nếu bạn chắc chắn rằng giá trị sẽ không bị thay đổi khi chạy mã của bạn. Ví dụ, khi bạn khai báo một câu luôn luôn giữ nguyên.

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.