อะไรคือความแตกต่างระหว่างคำหลัก "const" และ "สุดท้าย" ใน Dart


173

ความแตกต่างระหว่างconstและfinalคำหลักใน Dart คืออะไร


1
นี่คือรายละเอียดบางอย่างเกี่ยวกับconst: stackoverflow.com/questions/51576209/ …และการอธิบายอย่างง่ายที่จะfinalเป็นค่าคงที่ (ไม่สามารถมอบหมายหรือมอบหมายใหม่เมื่อสร้างด้วยคำหลักสุดท้าย) และคุณต้องเริ่มต้นอีกครั้ง
Blasanka

คำตอบ:


236

มีโพสต์บนเว็บไซต์ของโผและมันอธิบายได้ค่อนข้างดี

สุดท้าย:

"final" หมายถึงการมอบหมายเดี่ยว: ตัวแปรสุดท้ายหรือฟิลด์ต้องมี initializer เมื่อกำหนดค่าแล้วค่าสุดท้ายของตัวแปรจะไม่สามารถเปลี่ยนแปลงได้ ปรับเปลี่ยนครั้งสุดท้ายตัวแปร


const:

"const" มีความหมายที่ซับซ้อนกว่าเล็กน้อยใน Dart const แก้ไขค่าค่าคุณสามารถใช้มันเมื่อสร้างคอลเลกชันเช่น const [1, 2, 3] และเมื่อสร้างวัตถุ (แทนของใหม่) เช่น const Point (2, 3) ที่นี่ const หมายความว่าสถานะเชิงลึกทั้งหมดของวัตถุสามารถกำหนดได้อย่างสมบูรณ์ในเวลารวบรวมและวัตถุนั้นจะถูกแช่แข็งและไม่เปลี่ยนรูปอย่างสมบูรณ์

วัตถุ Const มีคุณสมบัติและข้อ จำกัด ที่น่าสนใจสองประการ:

จะต้องสร้างจากข้อมูลที่สามารถคำนวณได้ในเวลารวบรวม วัตถุ const ไม่สามารถเข้าถึงสิ่งใด ๆ ที่คุณต้องการในการคำนวณ ณ รันไทม์ 1 + 2 เป็นนิพจน์ const ที่ถูกต้อง แต่ DateTime.now ใหม่ () ไม่ใช่

พวกมันอยู่ลึกล้ำเปลี่ยนแปลงไม่ได้ หากคุณมีฟิลด์สุดท้ายที่มีคอลเลกชันคอลเลกชันนั้นยังคงสามารถเปลี่ยนแปลงได้ หากคุณมีคอลเลกชัน const ทุกอย่างในนั้นจะต้องเป็น const ซ้ำด้วย

พวกเขาจะcanonicalized นี่คือการจัดเรียงของสตริงที่คล้ายกัน: สำหรับค่า const ที่กำหนดใด ๆ วัตถุ const เดียวจะถูกสร้างขึ้นและนำกลับมาใช้ใหม่ไม่ว่ากี่ครั้งที่การแสดงออกของ const จะถูกประเมิน


ดังนั้นสิ่งนี้หมายความว่าอย่างไร

Const:
หากค่าที่คุณได้รับการคำนวณ ณ รันไทม์ ( new DateTime.now()ตัวอย่างเช่น) คุณไม่สามารถใช้ const สำหรับมันได้ แต่ถ้าค่าที่เป็นที่รู้จักกันที่รวบรวมเวลา ( const a = 1;) แล้วคุณควรใช้มากกว่าconst finalมี 2 แตกต่างกันมากระหว่างมีและconst finalประการแรกถ้าคุณกำลังใช้constคุณต้องประกาศว่ามันเป็นมากกว่าแค่static const constประการที่สองถ้าคุณมีคอลเลกชันภายในทุกอย่างที่อยู่ในconst constหากคุณมีfinalคอลเลกชันภายในทุกอย่างที่เป็นไม่ได้ final

Final:
finalควรใช้มากกว่าconstถ้าคุณไม่ทราบค่า ณ เวลารวบรวมและมันจะถูกคำนวณ / คว้าที่ runtime หากคุณต้องการการตอบสนอง HTTP finalที่ไม่สามารถเปลี่ยนแปลงได้ถ้าคุณต้องการที่จะได้รับบางสิ่งบางอย่างจากฐานข้อมูลหรือถ้าคุณต้องการที่จะอ่านจากไฟล์ท้องถิ่นใช้ อะไรที่ไม่เป็นที่รู้จักที่รวบรวมเวลาที่ควรจะเป็นมากกว่าfinalconst


ด้วยสิ่งที่กล่าวมาทั้งconstและfinalไม่สามารถกำหนดใหม่ได้ แต่ฟิลด์ในfinalวัตถุตราบใดที่พวกเขาไม่ได้constหรือfinalสามารถกำหนดใหม่ได้ (ไม่เหมือนconst)


3
คีย์เวิร์ด const ใช้เพื่อแสดงค่าคงที่เวลาคอมไพล์ ตัวแปรที่ประกาศโดยใช้คำหลัก const นั้นถือเป็นที่สุด
อรุณจอร์จ

1
@Meyi เราควรใช้constเมื่อใดและเมื่อfinalใด คุณรู้หรือไม่ว่าการใช้ตัวพิมพ์บางตัวสำหรับตัวดัดแปลงเหล่านี้
CopsOnRoad

4
@CopsOnRoad คุณสามารถตรวจสอบวิดีโอนี้ได้Dart Const vs Final
Lemuel Ogbunude

2
ประโยคสุดท้ายนั้นเป็นผลรวมที่ดีจริงๆ ขอบคุณสำหรับสิ่งนั้น
Yster

เราควรจะสนใจว่า const เป็นตัวเลือกหรือไม่? ประสิทธิภาพเพิ่มขึ้นหรือไม่
CodeGrue

63

const

ราคาจะต้องรู้จักที่รวบรวมเวลา , 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;
}

อื่นใช้งานที่สำคัญของการ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 เริ่มต้นconstซึ่งมีรายการ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 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

  • ตัวแปรสุดท้ายสามารถตั้งค่าได้เพียงครั้งเดียวและจะเริ่มต้นได้เมื่อเข้าถึง (ตัวอย่างจากส่วนของรหัสด้านล่างหากคุณใช้ค่าbiggestNumberOndiceเพียงค่าจะเริ่มต้นได้และหน่วยความจำจะได้รับการกำหนด)
  • 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;
}

2
ผมคิดว่าเป็นวิธีที่ดีกว่าที่จะถามคำถามคือเมื่อจะชอบเริ่มต้นรันไทม์เริ่มต้นในช่วงเวลารวบรวม ....
Faisal Naseer

และการที่คุณสามารถให้คำปรึกษาคำตอบ @Meyi และยังไม่ไปที่ลิงค์ของบทความจากโพสต์ของเขายอดเยี่ยม :)
Faisal Naseer

2

ทั้งสองfinalและconstป้องกันไม่ให้ตัวแปรถูกกำหนดใหม่ (คล้ายกับวิธีการfinalทำงานใน Java หรือวิธีการconstทำงานใน JavaScript)

ความแตกต่างเกี่ยวกับวิธีการจัดสรรหน่วยความจำ หน่วยความจำถูกจัดสรรสำหรับfinalตัวแปรที่รันไทม์และสำหรับconstตัวแปรที่รวบรวมเวลา โมดิfinalฟายเออร์ควรเป็นที่นิยมใช้มากกว่าเนื่องจากตัวแปรของโปรแกรมจำนวนมากไม่ต้องการหน่วยความจำใด ๆ เนื่องจากลอจิกของโปรแกรมจะไม่เรียกให้มันเริ่มต้น ด้วยconstตัวแปรที่คุณกำลังบอกคอมพิวเตอร์ว่า "เฮ้ฉันต้องการหน่วยความจำสำหรับตัวแปรนี้ล่วงหน้าเพราะฉันรู้ว่าฉันต้องการมัน"

การคิดถึงพวกเขาด้วยวิธีนี้ทำให้ง่ายต่อการเข้าใจความแตกต่างในการใช้ไวยากรณ์ของพวกเขา ส่วนใหญ่finalตัวแปรอาจเป็นตัวแปรอินสแตนซ์ แต่constต้องเป็นstaticตัวแปรในคลาส นี่เป็นเพราะตัวแปรอินสแตนซ์ถูกสร้างขึ้นที่รันไทม์และconstตัวแปร - ตามคำนิยาม - ไม่ใช่ ดังนั้นconstตัวแปรในคลาสจะต้องเป็นstaticซึ่งหมายความว่าเพียงสำเนาเดียวของตัวแปรนั้นมีอยู่ในคลาสโดยไม่คำนึงว่าคลาสนั้นมีอินสแตนซ์หรือไม่

วิดีโอนี้แบ่งย่อยได้ค่อนข้างง่าย: https://www.youtube.com/watch?v=9ZZL3iyf4Vk

บทความนี้มีความลึกมากขึ้นและอธิบายถึงความแตกต่างทางความหมายที่สำคัญระหว่างทั้งสองนั่นคือfinalปรับเปลี่ยนตัวแปรและconstปรับเปลี่ยนค่าซึ่งจำเป็นอย่างยิ่งที่จะสามารถเริ่มต้นconstค่าที่สามารถทำได้ในเวลารวบรวม

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


2

final และ constในเรื่องปาเป้าทำให้เกิดความสับสนกับระดับที่เราคิดว่าทั้งคู่เหมือนกัน

เรามาดูความแตกต่าง:

PS ฉันรวมรูปภาพแทนข้อความเนื่องจากฉันไม่สามารถจัดระเบียบข้อมูลในรูปแบบ Stackoverflow .md ได้อย่างง่ายดาย


1

ถ้าคุณมาจากC++นั้นconstในDartคือconstexprในC++และfinalในDartคือในconstC++

ด้านบนใช้กับประเภทดั้งเดิมเท่านั้น อย่างไรก็ตามในDartวัตถุที่ทำเครื่องหมายfinalจะไม่สามารถเปลี่ยนแปลงได้ในแง่ของสมาชิก


2
เรียงจาก ฉันคิดว่าคุณสามารถพูดสิ่งนี้สำหรับประเภทดั้งเดิม แต่ไม่ใช่สำหรับวัตถุ constใน C ++ มักใช้เพื่อระบุว่าวัตถุนั้นไม่สามารถเปลี่ยนแปลงได้ผ่านการอ้างอิงหรือตัวชี้เฉพาะ finalใน Dart ไม่ได้ป้องกันมิให้วัตถุกลายพันธุ์ผ่านตัวแปรนั้น
jamesdlin

0

คุณไม่สามารถ initialise ใช้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

ควรใช้คำหลักใด

ตัวอย่างง่าย ๆ สำหรับทั้งคู่: ใช้ขั้นตอนสุดท้าย: หากคุณไม่รู้ว่าค่าอะไรที่จะใช้ในการรวบรวมเวลา ตัวอย่างเช่นเมื่อคุณต้องการรับข้อมูลจาก API สิ่งนี้จะเกิดขึ้นเมื่อใช้รหัสของคุณ

ใช้ const: หากคุณแน่ใจว่าค่าจะไม่เปลี่ยนแปลงเมื่อเรียกใช้รหัสของคุณ ตัวอย่างเช่นเมื่อคุณประกาศประโยคที่ยังคงเหมือนเดิม

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.