我非常受Rich Hickey倡导的数据管理方法的启发,并在Datomic中实现,数据从未就地变异,所有版本始终保存和查询,时间是第一个 -阶级观念.
当然,有专门的数据库匹配该描述,如Git,或任何其他源控制系统.问题是,是否有任何(或多或少)通用DBMS-es的关系,图形,层次,文档或任何其他风格可以有效地用于,例如,电子商务Web应用程序.或者Datomic是唯一的选择呢?
LinkedHashMap用于保留地图中的插入顺序,但这仅适用于可变地图.哪个是Map保留插入顺序的不可变实现?
据我所知,
可以更改可变字符串,并且不能更改不可变字符串.
在这里,我想像这样更改String的值,
String str="Good";
str=str+" Morning";
Run Code Online (Sandbox Code Playgroud)
和其他方式是,
StringBuffer str= new StringBuffer("Good");
str.append(" Morning");
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,我试图改变其价值str.任何人都可以告诉我,这两种情况有什么不同,并给我清晰的可变和不可变对象的图片.
我在一些项目的过程中开发了一种用于创建不可变(只读)对象和不可变对象图的模式.不可变对象具有100%线程安全的优点,因此可以跨线程重用.在我的工作中,我经常在Web应用程序中使用此模式来配置设置以及我在内存中加载和缓存的其他对象.缓存对象应始终是不可变的,因为您希望保证它们不会意外更改.
现在,您可以轻松地设计不可变对象,如下例所示:
public class SampleElement
{
private Guid id;
private string name;
public SampleElement(Guid id, string name)
{
this.id = id;
this.name = name;
}
public Guid Id
{
get { return id; }
}
public string Name
{
get { return name; }
}
}
Run Code Online (Sandbox Code Playgroud)
这对于简单的类来说很好 - 但是对于更复杂的类,我不喜欢通过构造函数传递所有值的概念.在属性上设置setter是更理想的,构建新对象的代码更容易阅读.
那么如何使用setter创建不可变对象?
好吧,在我的模式中,对象开始是完全可变的,直到你用一个方法调用冻结它们.一旦一个对象被冻结,它将永远保持不变 - 它不能再次变成一个可变对象.如果您需要对象的可变版本,则只需克隆它即可.
好的,现在谈谈一些代码.我在下面的代码片段中试图将模式简化为最简单的形式.IElement是所有不可变对象必须最终实现的基接口.
public interface IElement : ICloneable
{
bool IsReadOnly { get; }
void MakeReadOnly();
}
Run Code Online (Sandbox Code Playgroud)
Element类是IElement接口的默认实现:
public abstract class Element : IElement
{
private bool immutable;
public …Run Code Online (Sandbox Code Playgroud) 有什么区别:
class Person(name: String, age: Int) {
def say = "My name is " + name + ", age " + age
}
Run Code Online (Sandbox Code Playgroud)
和
class Person(val name: String, val age: Int) {
def say = "My name is " + name + ", age " + age
}
Run Code Online (Sandbox Code Playgroud)
我可以将参数声明为vars,并在以后更改它们的值吗?例如,
class Person(var name: String, var age: Int) {
age = happyBirthday(5)
def happyBirthday(n: Int) {
println("happy " + n + " birthday")
n
}
}
Run Code Online (Sandbox Code Playgroud) 我正在观看关于Java的演讲,有一次,讲师说:
"可变性是可以的,分享是好的,共享的可变性是魔鬼的工作."
他所指的是以下一段代码,他认为这是一种"极其糟糕的习惯":
//double the even values and put that into a list.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 1, 2, 3, 4, 5);
List<Integer> doubleOfEven = new ArrayList<>();
numbers.stream()
.filter(e -> e % 2 == 0)
.map(e -> e * 2)
.forEach(e -> doubleOfEven.add(e));
Run Code Online (Sandbox Code Playgroud)
然后他继续编写应该使用的代码,即:
List<Integer> doubleOfEven2 =
numbers.stream()
.filter(e -> e % 2 == 0)
.map(e -> e * 2)
.collect(toList());
Run Code Online (Sandbox Code Playgroud)
我不明白为什么第一段代码是"坏习惯".对我而言,他们都达到了同样的目标.
在Scala中,有什么区别
val a = 1
Run Code Online (Sandbox Code Playgroud)
和
final val fa = 1
Run Code Online (Sandbox Code Playgroud) 我发现人们声称使用类中的所有只读字段并不一定使该类的实例不可变,因为即使在初始化(构造)之后,仍有"方法"来更改只读字段值.
怎么样?有什么方法?
所以我的问题是我们什么时候才能在C#中真正拥有一个"真正的"不可变对象,我可以安全地在线程中使用它?
匿名类型也创建不可变对象吗?有人说LINQ在内部使用了不可变的对象.究竟怎么样?
问题很简单.可以改变其内部状态而不能从外部观察的类型是否可以被认为是不可变的?
简化示例:
public struct Matrix
{
bool determinantEvaluated;
double determinant;
public double Determinant
{
get //asume thread-safe correctness in implementation of the getter
{
if (!determinantEvaluated)
{
determinant = getDeterminant(this);
determinantEvaluated = true;
}
return determinant;
}
}
}
Run Code Online (Sandbox Code Playgroud)
更新:澄清线程安全问题,因为它导致分心.
immutability ×10
c# ×3
java ×3
scala ×3
.net ×1
collections ×1
constructor ×1
database ×1
datomic ×1
dictionary ×1
java-8 ×1
java-stream ×1
mutable ×1
readonly ×1
scope ×1
string ×1
stringbuffer ×1
survey ×1