为什么这个类在scala中需要抽象?

为什么这个类在scala中需要抽象?,scala,Scala,在java和c#中,我可以编写以下代码: class Tree { Tree left; Tree right; } trait Tree{ val left:Tree val right:Tree } 但在斯卡拉: class Tree{ val left:Tree val right:Tree } 我需要为类添加摘要,或编写: val left:Tree=new Tree() 我可以这样写: class Tree { Tree left; Tree right; }

在java和c#中,我可以编写以下代码:

class Tree {
 Tree left;
 Tree right;
}
trait Tree{
 val left:Tree
 val right:Tree
}
但在斯卡拉:

class Tree{
 val left:Tree
 val right:Tree
}
我需要为类添加摘要,或编写:

val left:Tree=new Tree()
我可以这样写:

class Tree {
 Tree left;
 Tree right;
}
trait Tree{
 val left:Tree
 val right:Tree
}
但为什么我使用类,我“不得不”和抽象?我认为这不是一个好的设计


谢谢

之所以发生这种情况,是因为scala有时将
val
def
视为类似方法的声明。请允许我详细说明,例如,我们有下一个Scala示例:

class Example {
  val a: String = "example"
}
val example = new Example()
println(example.a)
您可能会看到
a
声明为字段。与Java不同,我们可以轻松地将此声明更改为
def
,并且所有内容都保持编译状态:

class Example {
  def a: String = "example"
}
val example = new Example()
println(example.a)
在Java的情况下(不确定是否使用C#我从未使用过它),如果希望通过getter方法访问字段,则需要将所有调用位置从字段更改为方法访问

现在,,您可以考虑<代码> Val<代码>,正如我们所说的一种急切的缓存<代码> DEF版本——如果是,则声明“代码> Val< /CODE”,而实际上不赋值赋值被编译器认为是没有实现的声明方法,这就是为什么编译器说<代码>树>代码>是一个抽象类——因为<代码>左< /代码>
right
没有值,因此它们是抽象的。为了使其非抽象,如果要继续使用可变结构,则需要为字段分配一个值或使用
var
,例如:

class Example {
  val a: String = "example"
}
val example = new Example()
println(example.a)

Scatie:

之所以发生这种情况,是因为scala有时将
val
def
视为类似方法的声明。请允许我详细说明,例如,我们有下一个Scala示例:

class Example {
  val a: String = "example"
}
val example = new Example()
println(example.a)
您可能会看到
a
声明为字段。与Java不同,我们可以轻松地将此声明更改为
def
,并且所有内容都保持编译状态:

class Example {
  def a: String = "example"
}
val example = new Example()
println(example.a)
在Java的情况下(不确定是否使用C#我从未使用过它),如果希望通过getter方法访问字段,则需要将所有调用位置从字段更改为方法访问

现在,,您可以考虑<代码> Val<代码>,正如我们所说的一种急切的缓存<代码> DEF版本——如果是,则声明“代码> Val< /CODE”,而实际上不赋值赋值被编译器认为是没有实现的声明方法,这就是为什么编译器说<代码>树>代码>是一个抽象类——因为<代码>左< /代码>
right
没有值,因此它们是抽象的。为了使其非抽象,如果要继续使用可变结构,则需要为字段分配一个值或使用
var
,例如:

class Example {
  val a: String = "example"
}
val example = new Example()
println(example.a)

Scatie:

你可以写的原因

class Tree {
    Tree left;
    Tree right;
}
在Java和C中,#是因为默认情况下字段初始化为
null
(或根据类型初始化为
0
,等等)。Scala的设计人员认为这是一个坏主意,您需要对其进行初始化。所以近似的Scala等价物是

class Tree {
  // note, not val
  var left: Tree = null
  var right: Tree = null
}

这是合法的(但可能不是你真正想要使用的东西)。

你可以写的原因

class Tree {
    Tree left;
    Tree right;
}
在Java和C中,#是因为默认情况下字段初始化为
null
(或根据类型初始化为
0
,等等)。Scala的设计人员认为这是一个坏主意,您需要对其进行初始化。所以近似的Scala等价物是

class Tree {
  // note, not val
  var left: Tree = null
  var right: Tree = null
}
这是合法的(但可能不是你真正想要使用的东西)

但如果我使用类,为什么我“必须”和抽象

你必须用
abstract
关键字标记你的类,因为你的类是抽象的。它不可能被实例化

我认为这不是一个好的设计

好的设计是主观的。Scala的设计者认为,在这种情况下,显式的设计,而不是使类自动抽象,是一种好的设计。我猜Scala社区的大多数人都同意他们的观点

你不同意,那完全没关系

但如果我使用类,为什么我“必须”和抽象

你必须用
abstract
关键字标记你的类,因为你的类是抽象的。它不可能被实例化

我认为这不是一个好的设计

好的设计是主观的。Scala的设计者认为,在这种情况下,显式的设计,而不是使类自动抽象,是一种好的设计。我猜Scala社区的大多数人都同意他们的观点


你不同意,这完全没关系。

所以你有一些抽象的东西,但不想将其定义为抽象的?@jwvh不,你确实需要在Java中将抽象类标记为
abstract
(据我记忆,还有C);第一个类不是抽象类,因为它的字段被初始化为
null
。所以您有一些抽象的东西,但不想将其定义为抽象类?@jwvh否,您确实需要在Java中将抽象类标记为
abstract
(我记得是C);第一个类不是抽象类,因为它的字段初始化为
null