Types 具有类型和值限制以及默认值的Erlang记录
我试图写一份代表银行账户的记录:Types 具有类型和值限制以及默认值的Erlang记录,types,erlang,default-value,records,restrictions,Types,Erlang,Default Value,Records,Restrictions,我试图写一份代表银行账户的记录: -record(account, { name :: atom(), type :: atom(), balance = 0 :: integer() }). 我还想限制余额始终为=0。我该怎么做?类似于balance=0::0 | pos_integer()的东西可能会起作用 edit不确定它是否存在,但非负整数()会更好: balance = 0 :: non_neg_in
-record(account, { name :: atom(),
type :: atom(),
balance = 0 :: integer() }).
我还想限制余额始终为
=0
。我该怎么做?类似于balance=0::0 | pos_integer()
的东西可能会起作用
edit不确定它是否存在,但非负整数()
会更好:
balance = 0 :: non_neg_integer()
正如其他人所指出的,类型规范仅仅是分析工具(如和)的输入。如果需要强制执行不变量
余额>=0
,则应封装帐户类型,仅可由遵守该不变量的函数访问:
-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
<>注意到,这类似于一个类,在面向对象语言中,如java或C++。通过限制对“受信任”构造函数和访问器的访问,不变量得以强制执行
此解决方案不提供防止恶意修改
余额
字段的保护。另一个模块中的代码完全有可能忽略“不透明”类型规范并替换记录中的余额字段(因为)。我也不知道存在这种情况。非常感谢!请注意,正如Robert Virding所说,这只是供读者、文档或工具使用的信息。它不会阻止平衡为负或其他任何东西(如原子)。如果它在代码中很重要,则在使用它和/或修改平衡之前,您必须使用类似于is_integer(B)和B>=0的保护。谢谢@Pascal,我一定会使用这些保护。:)请注意,虽然可以将类型声明为非负整数,但在运行时不会强制执行任何操作,它实际上只是一个注释。您可以将“平衡”字段设置为您选择的任何值和任何类型。@rviding如何在运行时强制执行此行为(没有函数保护)?或者这种伪静态类型在Erlang中根本不存在吗?你不能!Erlang过于动态,因此该语言中不存在静态类型,编译器也不使用此信息。它仅用于文档和类型检查工具透析器。感谢您的示例和警告!