我有一个非常基本和简单的Scala问题。例如,我有一个类似的Java类
class Dataset{
private List<Record> records;
Dataset(){
records = new ArrayList<Record>()
}
public void addItem(Record r){
records.add(r)
}
}
当我尝试在Scala中编写相同的类时,我陷入了一些错误:
class RecordSet() {
private var dataset:List[Record]
def this(){
dataset = new List[Record]
}
def addRecord(rd: Record)={
dataset :+ rd
}
}
我无法声明类似(私有var数据集:List [Record])的List变量 并且无法编写默认的构造函数。
答案 0 :(得分:2)
这是如何复制问题中提到的Java代码:
// defining Record so the code below compiles
case class Record()
// Here is the Scala implementation
class RecordSet(private var dataset:List[Record]) {
def addRecord(rd: Record)={
dataset :+ rd
}
}
一些解释:
在Scala中,定义类时,可以将参数传递给类定义。例如:class Foo(num:Int, descr:String)
Scala会自动使用给定的参数为您创建一个主构造函数。因此,您现在可以像new Foo(1, "One")
一样实例化Foo。在Java中,您必须显式定义参数接受构造函数。
您必须知道,传递的参数不会自动成为该类的实例成员。尽管可以,但是可以告诉Scala将其设为实例成员。有多种方法可以执行此操作,一种方法是在参数前面加上var
或val
。例如class Foo(val num:Int, val descr:String)
或class Foo(var num:Int, var descr:String)
。区别在于使用val
时,实例变量是不可变的。使用var
,它们是可变的。
此外,默认情况下,Scala将生成的实例成员将是公共的。这意味着可以直接从对象的实例访问它们。例如:
val foo = new Foo(1, "One")
println(foo.num) // prints 1.
如果希望它们是私有的,则可以在定义中添加private关键字。这样就变成了:
class Foo(private var num:Int, private var desc:String)
代码无法编译的原因是您定义了一个名为this()
的方法,该方法用于创建多个构造函数。 (而不是创建一个初始化私有字段的构造函数,这是根据您共享的Java代码判断的意图)。您可以在Google上搜索多个构造函数或辅助构造函数,以了解有关此内容的更多信息。
答案 1 :(得分:1)
就像爸爸告诉您的代码中的问题一样,实际上您使用this
关键字创建了auxilary
构造函数,该构造函数具有一些限制,例如the first line of your auxilary constructor must be another constructor (auxilary/primary)
。因此,您不能使用这种方法来创建类。
private var dataset:List[Record]
中编写这样的行,因为它被视为抽象类(未提供定义)。现在输入代码。通常在Scala中,我们不喜欢可变性,因为它在我们的函数中引入了副作用(这不是功能性的方式,但是由于scala并非纯粹是功能性的,因此您也可以使用可变性。)
以Scala方式,代码应如下所示:
class RecordSet(private val dataset:List[Record]) {
def addRecord(rd: Record): RecordSet ={
new RecordSet(dataset :+ rd)
}
}
现在,上述类别中没有可变性。每当将元素添加到数据集时,都会创建一个RecordSet的新实例。因此没有可变性。
但是,如果您必须在应用程序中使用相同的类引用,请对数据集使用可变集合,如下所示:
class RecordSet(private val dataset:ListBuffer[Record]) {
def addRecord(rd: Record): ListBuffer[Record] ={
dataset += rd
}
}
以上代码将新记录添加到具有相同类引用的现有数据集中。