字符串是不可变的,这意味着,一旦创建它们就无法更改.
那么,这是否意味着如果你用+ =附加的东西比你创建一个StringBuffer并附加文本那么需要更多的内存?
如果你使用+ =,每次必须保存在内存中时你会创建一个新的'对象',不是吗?
我想仅使用不可变对象构建我的域模型.但我也想使用具有val字段的特征并将一些功能移到特征中.请看下面的例子:
trait Versionable {
val version = 0
def incrementVersion = copy(version=version+1)
}
Run Code Online (Sandbox Code Playgroud)
不幸的是这样的代码不起作用 - 对于特性Versionable,复制方法是未知的.
我认为为每个特征和类生成复制方法会很好.这样的方法应该创建对象的浅拷贝,并使用与原始对象相同的类型返回它,并根据传递给方法的参数修改给定的字段.
所以在下面的例子中:
class Customer(val name: String) extends Versionable {
def changeName(newName: String) = copy(name = newName)
}
val customer = new Customer("Scot")
Run Code Online (Sandbox Code Playgroud)
customer.changeName("McDonnald") 应该返回一个对象实例 Customer(version = 0, name = "McDonnald")
和
customer.incrementVersion 还应该返回一个对象实例 Customer(version = 1, name = "Scot")
据我所知,目前Scala中缺少此类功能不允许使用不可变类和特征而不会污染具有特征字段的类构造函数.在我的示例中,我不想将参数命名版本引入Customer类,因为版本处理的功能我想要封装在Versionable特性中.
我知道案例类中复制方法的功能以及使用默认参数在类中编写自己的复制方法的能力 - 但我认为这个功能并不能解决我的问题,因为在特征中不可能使用这种复制方法.现有功能的另一个缺点是使用复制方法的父类返回父类而不是实际复制的对象类.
我的问题:
1)您是否知道如何以优雅的方式处理上述示例.我对Scala很新,所以也许已经有了很好的解决方案.在我看来,优雅的解决方案应具有以下功能:
不应该使用反射
不应该使用序列化
应该快
应该在编译时可以验证
2)您如何考虑编写编译器插件来为我上面的示例生成复制方法的代码?是否可以使用编译器插件来做到这一点?您有任何示例或提示如何做到这一点?
我正在玩弄LINQPad附带的一些linq样本.在"Nutshell中的C#3.0"文件夹中,在Chater 9 - Grouping下,有一个名为"按多个键分组"的示例查询.它包含以下查询:
from n in new[] { "Tom", "Dick", "Harry", "Mary", "Jay" }.AsQueryable()
group n by new
{
FirstLetter = n[0],
Length = n.Length
}
Run Code Online (Sandbox Code Playgroud)
我将字符串"Jon"添加到数组的末尾以获得实际的分组,并得出以下结果:

这正是我所期待的.然后,在LINQPad中,我去了相同查询的VB.NET版本:
' Manually added "Jon"
from n in new string() { "Tom", "Dick", "Harry", "Mary", "Jay", "Jon" }.AsQueryable() _
group by ng = new with _
{ _
.FirstLetter = n(0), _
.Length = n.Length _
} into group
Run Code Online (Sandbox Code Playgroud)
结果没有正确地将Jay/Jon组合在一起.

把我的头发拉了一下之后,我发现这篇MSDN文章讨论了VB.NET的匿名类型.在VB.NET中,默认情况下它们是可变的,而不是C#,它们是不可变的.在VB中,您需要添加Key关键字以使它们不可变.所以,我将查询更改为此(注意添加Key):
from n in new string() …Run Code Online (Sandbox Code Playgroud) 我正在使用相当多的不可变集合,我很好奇如何使用Gson对它们进行反序列化.由于没有人回答我自己找到了解决方案,我正在简化问题并提出自己的答案.
我有两个问题:
Deserializer为所有人写一个单一的工作ImmutableList<XXX>?ImmutableList<XXX>?你好,这里有jQuery的新菜鸟,我想知道jQuery对象是不可变的.例如:
var obj1 = $("<tag></tag>");
var obj2 = obj1.append("something");
Run Code Online (Sandbox Code Playgroud)
obj1和obj2是否相同意味着obj2会引用obj1?
更新:
上面的例子有点划伤我想知道的表面,一个更准确的问题是:如果我从jQuery api链接函数将返回相同的对象或新的(如Java中的字符串的情况)?
我正在寻找一个可以从多个线程访问的只读字典.虽然ConcurrentDictionary暴露了这样的功能,但我不希望有开销和奇怪的API.
.Net 4.5虽然提供了这样的类,但文档指出只有静态调用才是安全的.
我想知道为什么?
C++编程语言第四版 - Bjarne Stroustrup :(强调我的)
2.2.3.常量
在少数地方,语言规则需要常量表达式(例如,数组边界(§2.2.5,§7.3),案例标签(§2.2.4,§9.4.2),一些模板参数(§25.2),以及使用constexpr声明的常量).在其他情况下,编译时评估对性能很重要. 与性能问题无关,不可变性(具有不可更改状态的对象)的概念是一个重要的设计问题(第10.4节).
似乎Stroustrup在这里建议constexpr确保一个对象的不变性比传统的const声明更好.它是否正确?是否有方法,使constexpr可以更安全/比不易挥发const,或不斯特劳斯只意味着因为有很多方法可以使用constexpr不与支持const(见是constexpr真正需要的?),在这种情况下不变性可以使用保证constexpr?
在给我的问题具体化之前,让我提供一些背景知识:我的主要编程语言是C++和Java.使用C++时,我发现应用const正确性很重要,即声明这样的函数:
A::DoSomething( const B& arg ); // guarantees that arg is not modified
A::DoSomething() const; // guarantees that the object of type A is not modified
A::DoSomething( const B& arg ) const; // both of the above
Run Code Online (Sandbox Code Playgroud)
事实上,我经常希望这const是默认值,并且必须以某种方式标记被修改的对象.
我使用的主要原因const是:
众所周知,Java没有const关键字(你不能做上面的事情final),这个事实在这里已经讨论过,例如参见:Java中的const(C++)的等价物.
通常提出的Java替代方法是使您的类不可变.虽然这不是完全替代,const因为它适用于每个类而不是每个使用类的上下文,但在大多数情况下它对我来说都可以正常工作.
但是不可变类有一个大问题:不可变性并不明显.要知道一个类是否真的是不可变的,据我所知,你基本上必须检查完整的源代码.任何方法都可以有一个后门,通过它可以修改对象.
那么有更简单的方法来检查不变性吗?或者是否有任何最佳实践以某种方式标记一个类是不可变的?
注意:我知道这两种语言都提供了绕过constness或immutability的"邪恶伎俩":C++ const_cast和Java都有反思.但是对于我的问题的背景,我们假设这些都没有被使用.
这是在使用thunk时编写动作的一种方法,这会导致非常简单的reducer.
getCurrentUserPicture(){
return (dispatch,getState) => {
dispatch({type: "isloading", isLoading: true}); // shows a loading dialog
dispatch({type: "errorMessage"}); // clear errorMessage
dispatch({type: "warningMessage"}); // clear warningMessage
const userId = getState().user.get("currentUser").id;
getUserPicture(userId) // get from backend
.then(picture => {
dispatch({type: "userPicture", picture});
dispatch({type: "isLoading", isLoading: false});
}
)
.catch(e=>{
dispatch({type: "errorMessage", e});
dispatch({type: "isLoading", isLoading: true});
}
)
}
}
Run Code Online (Sandbox Code Playgroud)
减速机包括:
export reducer(state = initialState, action = {}) {
switch(action.type) {
case "isLoading":
return state.set("isLoading", action.isLoading)
Run Code Online (Sandbox Code Playgroud)
这是另一种方法,其中动作"更清洁"但减速器更复杂:
getCurrentUserPicture(){
return (dispatch,getState) => { …Run Code Online (Sandbox Code Playgroud) 我想要一个返回一个数组的函数,但是我希望返回的数组是只读的,所以当我尝试更改其内容时,我应该收到警告/错误.
function getList(): readonly number[] {
return [1,2,3];
}
const list = getList();
list[2] = 5; // This should result in a compile error, the returned list should never be changed
Run Code Online (Sandbox Code Playgroud)
这可以在TypeScript中实现吗?
immutability ×10
java ×3
.net-4.5 ×1
adapter ×1
c# ×1
c++11 ×1
concurrency ×1
const ×1
constexpr ×1
dictionary ×1
gson ×1
javascript ×1
jquery ×1
linq ×1
linqpad ×1
mutability ×1
oop ×1
reactjs ×1
readonly ×1
redux ×1
redux-thunk ×1
scala ×1
scala-2.8 ×1
string ×1
stringbuffer ×1
traits ×1
typescript ×1
vb.net ×1