代码之家  ›  专栏  ›  技术社区  ›  tstenner

为什么Scala没有C++类的const语义?

  •  20
  • tstenner  · 技术社区  · 15 年前


    变量: const int i=5;
    val i=5 但是,这只会阻止重新分配,而不会更改对象,如以下示例所示:
    C++:

    const int i[]={1,2,3,4};
    i[2]=5; //error
    斯卡拉:
    val a=Array(1,2,3,4)
    a(2)=5 //a is now Array(1, 2, 5, 4)

    成员函数的情况更糟:
    C++:

    class Foo {
    int i;
    int iPlusFive() const {return i+5;}
    int incrementI(){ return ++i; }
    }
    我可以肯定,调用iPlusFive不会改变对象,也不会意外地调用const对象上的incrementI。

    当涉及到集合时,C++用const集合继续它的正确正确的条目:简单地声明向量为const,并且不能改变它。分配 non-const vector<Int> const vector<Int> 编译器不会复制任何内容,并且会阻止您更改now const集合中的任何内容。

    斯卡拉有scala.collection.mutable变量不管怎样scala.collection.immutable不可变。无论如何,您不能仅将可变集合转换为不可变集合,而且您仍然可以使用非常量成员函数更改收集的对象。

    Margus建议使用 import scala.collection.mutable

    import scala.collection.mutable.HashMap
    import scala.collection.immutable.{HashMap => ConstHashMap}
    这将使可变哈希图可用作HashMap和不变的ALS CuthHasMMAP,但是我仍然更喜欢C++方法。
    4 回复  |  直到 15 年前
        1
  •  10
  •   Silvio Bierman    15 年前

    我不喜欢C++ const逻辑,它是关于引用而不是引用的对象。如果我有一个“const T*”,就不能保证持有非const指针的人不会修改对象的状态。因此,它不能以任何方式帮助避免多线程系统中的竞争条件,也不能帮助实现持久容器。

    在我看来,有一个不可变类的概念是非常有帮助的,而在标准库中缺少不可变容器在任何语言中都是错误的。由于这些应该表现出可观察的不变性,但出于效率原因,可能需要能够更改内部/不可见状态,因此我认为const语法没有什么帮助。

        2
  •  6
  •   xan    15 年前

    因为C++在复杂系统中不是很好。

    我可以肯定,调用iPlusFive不会改变对象,也不会意外地调用const对象上的incrementI。

    Const只是编译器读取的文档。文档通常是有用的,但有时是误导性的。

    聚合是const经常崩溃的地方。例如,我经常想声明一个方法不会改变向量,但是可以改变它的一个成员(或者返回一个非常量成员引用)。我必须使所有的const或所有的nonconst或发明新的类型变化为每一个组合。

        3
  •  5
  •   Vasil Remeniuk    15 年前

    在我看来,Scala只是提供了更大的灵活性,不会混淆引用的不变性和它背后结构的[可能]易变性,使您能够针对所处理的问题做出设计决策。

        4
  •  3
  •   Margus    15 年前

    所有的Scala代码都被翻译成Java代码,这就是我为什么用Java做例子的原因。

    以下是如何在Java中执行此操作:

        Integer x[] = new Integer[]{1,2,3,4}; 
        final List<Integer> CONST = Collections.unmodifiableList(Arrays.asList(x));
    

    . 如果您仍要修改常量集合,则需要复制并修改它。

    来源:链接

    Java不提供 const数组:即 可以为一个新的数组交换(C++) 但它的元素是不能改变的。 功能,解决方案是 对任何其他对象的只读访问 如下所述。所以有几个

    • 您可以通过将列表传递到 集合.不可修改列表()(尽管如此) 在本例中,变量为 声明为列表类型,而不是类型 这标志着它是“不可修改”的 下面讨论,任何试图修改 它将在运行时被发现);
    • 可以围绕私有数组创建包装器对象,并提供 其要素;
    • 您可以使用只读IntBuffer(或FloatBuffer等):。。。

    资料来源: Java equivalents - const

    因此,Scala的等效值为:

        val A = Set(1, 2, 3, 4)
    

        val A = List(1, 2, 3, 4)
    

    这应该转化为:

        scala.collection.immutable.List[java.lang.Integer] A = List(1, 2, 3, 4)
    

    这也许可以解释我对IttayD评论的反应,为什么java 6不同于c++编译器:

    具体化泛型

    目前,实现了泛型 使用擦除,这意味着 在运行时可用,这使得 通过这种方式来支持 向后兼容旧版本 这将打破传统的非通用 代码。然而,尼尔·加夫特 建议仅使类型可恢复 如有规定,以免断裂 向后兼容性。

    资料来源: link

    资料来源: link

    ... 你不能只是把可变集合转换成不可变集合。。。

    import scala.collection.mutable
    

    资料来源: Scala Collection API

    val a = scala.collection.mutable.List[Int](1, 2, 3)
    val A = scala.collection.immutable.List[Int](a.toArray())