目前最大的限制是属性必须是可变的(译者注:即可写的),对象初始化器才能工作:它们首先调用对象的构造函数(本例中是默认的无参数构造函数),然后赋值给属性 setter。
仅初始化(init-only)属性解决了这个问题!它引入了一个 init 访问器,它是 set 访问器的变体,只能在对象初始化时调用:
public class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
有了这个声明,上面的客户端代码仍然是合法的,但是随后对 FirstName 和 LastName 属性的任何赋值都是错误的。
初始化(init) 访问器和只读(readonly)字段
因为 init 访问器只能在初始化期间调用,所以允许它们更改封闭类的只读(readonly)字段,就像在构造函数中一样。
public class Person
{
private readonly string firstName;
private readonly string lastName;
public string FirstName
{
get => firstName;
init => firstName = (value ?? throw new ArgumentNullException(nameof(FirstName)));
}
public string LastName
{
get => lastName;
init => lastName = (value ?? throw new ArgumentNullException(nameof(LastName)));
}
}
二、记录(record)
译者注:
原文中声明一个记录的 data class ** 联合关键字现在已经变成 record 关键字了,所以翻译过程中做了修正。
如果您想使单个属性不可变,那么仅初始化(init-only)属性是极好的。如果您想要整个对象是不可变的,行为像一个值,那么你应该考虑声明它为一个记录(record):
public record Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
对于记录(record),赋予了它一些类似值的行为,我们将在下面深入探讨。一般来说,记录更应该被看作是“值”——数据(data),而不是对象!它们并不具有可变的封装状态,相反,您需要通过创建表示新状态的新记录来表示其随时间的变化。它们不是由它们的身份(identity)确定的,而是由它们的内容确定的。
with 表达式
当使用不可变数据(data)时,一种常见的模式是从现有的值中创建新值来表示新状态。例如,如果我们的 person 要更改他们的 LastName,我们会将其表示为一个新对象,该对象是旧对象的副本,只是有不同的 LastName。这种技巧通常被称之为非破坏性突变(non-destructive mutation)。记录(record)不是代表 person 在一段时间内的 状态,而是代表 person 在给定时间点的 状态。
Java模板引擎能够处理HTMLXML,JavaScriptCSS甚至纯文本
原文:https://www.cnblogs.com/tuiop/p/13643145.html