Theo ghi nhận của người khác, các thông số kỹ thuật loại chỉ đơn thuần là đầu vào cho công cụ phân tích như PropEr và Dialyzer. Nếu bạn cần để thực thi bất biến balance >= 0
, các loại tài khoản nên được đóng gói, chỉ có thể truy cập đến chức năng mà tôn trọng bất biến:
-module(account).
-record(account, { name :: atom(),
type :: atom(),
balance = 0 :: non_neg_integer() }).
%% Declares a type whose structure should not be visible externally.
-opaque account() :: #account{}.
%% Exports the type, making it available to other modules as 'account:account()'.
-export_type([account/0]).
%% Account constructor. Used by other modules to create accounts.
-spec new(atom(), atom(), non_neg_integer()) -> account().
new(Name, Type, InitialBalance) ->
A = #account{name=Name, type=Type},
set_balance(A, InitialBalance).
%% Safe setter - checks the balance invariant
-spec set_balance(account(), non_neg_integer()) -> account().
set_balance(Account, Balance) when is_integer(Balance) andalso Balance >= 0 ->
Account#account{balance=Balance};
set_balance(_, _) -> error(badarg). % Bad balance
Chú ý cách này giống như một lớp học với lĩnh vực tư nhân trong các ngôn ngữ hướng đối tượng như Java hay C++ . Bằng cách hạn chế quyền truy cập vào các hàm tạo và các trình truy cập "đáng tin cậy", sự bất biến được thực thi.
Giải pháp này không cung cấp bảo vệ chống lại độc hại sửa đổi trường balance
. Hoàn toàn có thể cho mã trong mô-đun khác bỏ qua đặc tả loại "đục" và thay thế trường số dư trong bản ghi (kể từ records are just tuples).
Nguồn
2013-04-08 15:24:18
Lưu ý rằng mặc dù bạn có thể khai báo loại là số nguyên không âm này ** không ** thực thi bất cứ điều gì trong thời gian chạy, nó thực sự chỉ là một chú thích. Bạn có thể đặt trường số dư thành bất kỳ giá trị nào bạn chọn và bất kỳ loại nào. – rvirding
@rviding Làm cách nào để thực thi hành vi này khi chạy (không có bộ phận bảo vệ chức năng)? Hay việc gõ giả tĩnh này không tồn tại trong Erlang? – 2rs2ts
Bạn không thể! Erlang là quá năng động, do đó, gõ tĩnh không tồn tại trong ngôn ngữ và trình biên dịch không sử dụng thông tin này. Nó chỉ dành cho tài liệu hướng dẫn và cho công cụ kiểm tra kiểu dialyzer. – rvirding