Bạn đã thực sự hiểu mutable và immutable?

Chúng tôi vui mừng chia sẻ kiến thức về từ khóa Immutable la gi để tối ưu hóa nội dung trang web và chiến dịch tiếp thị trực tuyến. Bài viết cung cấp phương pháp tìm kiếm, phân tích và lựa chọn từ khóa phù hợp, cùng với chiến lược và công cụ hữu ích. Hy vọng thông tin này sẽ giúp bạn xây dựng chiến lược thành công và thu hút lưu lượng người dùng. Cảm ơn sự quan tâm và hãy tiếp tục theo dõi blog để cập nhật kiến thức mới nhất.

Bạn đã từng đọc hay nghe đâu đó nói rằng: mutable là giá trị có thể thay đổi được còn immutable là giá trị không thể thay đổi được. Nhưng bạn đã thực sự hiểu đúng nó vẫn chưa?

Bạn Đang Xem: Bạn đã thực sự hiểu mutable và immutable?

>> test = 3 # => 3 >> test # => 3 >> test = 2 * test # => 6 >> test # => 6

Bạn nghĩ đoạn code trên(trong ruby) chứng tỏ biến test liệu có phải là mutable không?

Trong ruby, kiểu numberboolean luôn là immutable

Rõ ràng trong ruby, kiểu number luôn là immutable nhưng ta vẫn thấy test ở ví dụ trên có thể thay đổi được. Lý do là vì bạn đã hiểu sai từ giá trị trong khái niệm.

Để hiểu đúng bạn phải biết được cách bộ nhớ lưu trữ một biến thế nào.

Nguyên tắc 2 Von Neumann: Lớp học máy tính chỉ truy cập tới tài liệu thông qua địa chỉ.

Bộ nhớ Khóa học gồm có 2 thành phần là địa chỉ bộ nhớtài liệu được lưu trữ trong bộ nhớ đó.

Khi có một phép toán như phép gán test = 3, rõ ràng bộ nhớ cần lưu trữ chữ test và giá trị 3 của nó vào bộ nhớ:

Địa chỉ bộ nhớ

Gía trị ô nhớ

xxx1

test

xxx2

3

Cần lưu trữ một thứ gì đó trong bộ nhớ để gán test = 3, giả sử ví dụ đơn giản bộ nhớ làm như sau để lưu trữ phép gán đó:

Địa chỉ bộ nhớ

Gía trị ô nhớ 1

Gía trị ô nhớ 2

xxx1

test

xxx2

3

Xem Thêm : Porsche là thương hiệu xe hấp dẫn nhất tại thị trường Mỹ

xxx0

xxx1

xxx2

Thế khi nào thì phép toán test = test * 2 được xem là mutable, khi nào thì được xem là immutable?

  • Phép toán trên được xem là mutable khi bộ nhớ thành như sau:

Địa chỉ bộ nhớ

Gía trị ô nhớ 1

Gía trị ô nhớ 2

Xem Thêm : Valar morghulis là gì

xxx1

test

xxx2

6

xxx0

Xem Thêm : Valar morghulis là gì

xxx1

xxx2

  • Phép toán trên được xem là immutable khi bộ nhớ thành như sau:

Địa chỉ bộ nhớ

Gía trị ô nhớ 1

Gía trị ô nhớ 2

Xem Thêm : Valar morghulis là gì

xxx1

test

xxx2

3

xxx3

6

xxx0

Xem Thêm : Valar morghulis là gì

xxx1

xxx3

Như bạn thấy, khi giá trị của biến không bị ghi đè mà được copy sang một nơi khác thì đó mới là immutable , từ giá trị ở khái niệm này đấy là giá trị đi với ô nhớ.

Còn xxx2 không còn được sử dụng trong immutable sẽ đi về đâu? Trong ruby có Khóa học dọn rác Garbage Collection sẽ tự động hóa xóa biến này đi khi nó đi thu dọn bộ nhớ.

Giờ chúng ta cũng có thể hiểu đoạn code ruby ở phần mở đầu rồi, nếu không tin chúng ta cũng có thể in ra object_id của nó để xác thực:

>> test = 3 # => 3 >> test # => 3 >> test.object_id # => 7 >> test = 2 * test # => 6 >> test # => 6 >> test.object_id # => 13

Thế vì sao lại phải cần tới immutable để làm gì khi nó giảm công suất của cục nhớ đi như vậy? Xem phần dưới.

Khi nào nên dùng mutable

Khi cần thay đổi một biến trong vòng lặp thì bạn nên dùng mutable

Nếu lặp n thành phần mà ta dùng immutable như sau:

String s = “”; for (int i = 0; i < n; ++i) { s = s + n; }

Trong java, kiểu Stringimmutable. Đoạn code trên cứ mỗi lần gán s = s + n là phải copy biến s cũ thành object khác rồi mới gán vào s mới được. Cứ mỗi lần copy s cũ là phải lặp số ký tự có trong s cũ để copy, dẫn tới thời kì tính toán của thuật toán là O(n²).

Ta có thể cải thiện thuật toán trên còn O(n) bằng phương pháp sử dụng mutable:

StringBuilder sb = new StringBuilder(); for (int i = 0; i < n; ++i) { sb.append(String.valueOf(n)); } String s = sb.toString();

Khi nào nên dùng immutable

Trong phần đông các trường hợp, bạn nên dùng immutableimmutable dễ hiểu và không xẩy ra bug liên quan tới reference còn mutable khiến cho code không tuân theo luồng suy nghĩ của lập trình viên, khó đọc, dễ khiến bug khó chịu liên quan tới reference.

VD1 gây bug:

/** @return the sum of the numbers in the list */ public static int sum(Listvàlt;Integervàgt; list) { int sum = 0; for (int x : list) sum += x; return sum; } /** @return the sum of the absolute values of the numbers in the list */ public static int sumAbsolute(Listvàlt;Integervàgt; list) { // let’s reuse sum(), because DRY, so first we take absolute values for (int i = 0; i < list.size(); ++i) list.set(i, Math.abs(list.get(i))); return sum(list); } // meanwhile, somewhere else in the code… public static void main(String[] args) { // … Listvàlt;Integervàgt; myData = Arrays.asList(-5, -3, -2); System.out.println(sumAbsolute(myData)); System.out.println(sum(myData)); }

  • Hàm sum tính tổng các thành phần của list truyền vào
  • Hàm sumAbsolute tính tổng kinh phí tuyệt đối của mỗi thành phần của list truyền vào. Vì không muốn tạo một mảng tạm trong hàm này nên lập trình viên đã dùng lại luôn list truyền vào để đỡ tốn bộ nhớ và hiệu năng.

Vấn để xẩy ra khi ai đó gọi hàm sumAbsolute(myData) với mảng bất kỳ myData rồi gọi tiếp sum(myData), khi gọi sumAbsolute(myData) thì hàm này đã làm mảng myData bị thay đổi nên hàm sum(myData) không còn gọi đúng với myData lúc đầu như dự kiến nữa.

VD2 gây bug:

private static Date startSpringDate = null; /** @return the first day of spring this year */ public static Date startOfSpring() { if (startSpringDate == null) startSpringDate = getStartOfSpring(); return startSpringDate; } // somewhere else in the code… public static void partyPlanning() { // let’s have a party one month after spring starts! Date partyDate = startOfSpring(); partyDate.setMonth(partyDate.getMonth() + 1); }

  • Kiểu Date trong java là mutable
  • Hàm startOfSpring() để lấy ngày trước tiên của ngày xuân, vì hàm getStartOfSpring() phía trong có xử lý rất phức tạp và tốn thời kì nên lập trình viên đã gán một biến global startSpringDate để lưu giá trị của startOfSpring() vào giúp khỏi phải gọi lại khi cấp thiết.

Vấn đề xẩy ra khi một lập trình viên nào đó muốn lấy ngày trước tiên của ngày xuân và thêm vào đó 1 tháng nữa như đoạn code trên. Vì startSpringDatepartyDate lúc này đang cùng trỏ đến một giá trị và kiểu Date trong java là mutable nên lúc gọi hàm partyDate.setMonth(… thì vô tình chung họ đã làm biến startSpringDate bị thay đổi, thiết kế lúc đầu nhằm mục tiêu biến này sẽ không bị thay đổi nên nó gây ra bug.

Link tham khảo:

https://launchschool.com/blog/references-and-mutability-in-ruby

https://en.wikipedia.org/wiki/Variable_(computer_science)

http://web.mit.edu/6.005/www/fa15/classes/09-immutability/

You May Also Like

About the Author: v1000