2011-06-03 78 views
7

我在scala中遇到了一个奇怪的问题。以下是我的代码,类员工扩展类Person必须在scala中覆盖val变量

但是这段代码不能编译,我有显式定义firstName和lastName为val变量。这是为什么 ?这是否意味着我必须在基类中重写val变量?目的是什么?

class Person(firstName: String, lastName: String) { 

} 

class Employee(override val firstName: String, override val lastName: String, val depart: String) 
    extends Person(firstName,lastName){ 

} 

回答

10

构造函数的输入参数不是val,除非你说他们是。如果它们已经存在,为什么要覆盖它们?

class Person(val firstName: String, val lastName: String) {} 
class Strange(
    override val firstName: String, override val lastName: String 
) extends Person("John","Doe") {} 
class Employee(fn: String, ln: String, val depart: String) extends Person(fn,ln) {} 

如果他们不瓦尔斯和你想丘壑,你并不需要重写:

class Person(firstName: String, lastName: String) {} 
class Employee(
    val firstName: String, val lastName: String, val depart: String 
) extends Person(firstName,lastName) {} 
+10

这个答案回答一个问题的问题。我将尝试回答。你必须在'Strange'类的'val'前面说'override'的原因是告诉编译器你不打算引入一个新字段。 'override'的意思大致是“在这里我声明了一些已经在父类中声明过的东西,并且不打算介绍一些不被继承的东西”。如果没有“覆盖”,val就意味着“请创建一个公共的,只读的字段”。但是Scala不允许两个val字段具有相同的名称。因此,“覆盖”是强制性的。 – 2013-07-31 20:02:44

+0

@TheodoreNorvell - 我的观点应该是,如果你只是用相同的字段来扩展原始类,那么就没有理由去创建覆盖。只需将它们作为参数传递,并让超类val成为val。 – 2013-07-31 20:41:24

+0

@RexKerr好的,这是一个很好的观点。你在问,“为什么有'覆盖val'?我回答说:“为什么'override'因为你有'val'?”。在我编写的代码中,我有类似的情况,但在我的情况下,子类是一个case类,所以构造函数参数自动为val。在这种情况下,编译器会给出一个错误消息,除非'override'关键字在那里,并且大概出于语法原因,它还需要'val'关键字。唯一的缺点是这两个额外的单词,并且该字段被初始化两次。 – 2013-08-02 12:40:16

0

除非我误解了你的意图,否则以下是如何扩展Person

Welcome to Scala version 2.8.0.final (Java HotSpot(TM) Client VM, Java 1.6.0_21). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> class Person(firstName: String, lastName: String) 
defined class Person 

scala> class Employee(firstName: String, lastName: String, depart: String) extends Person(firstName, lastName) 
defined class Employee 
6

由于构造函数的参数有没有人VAL/VAR声明,因为人是没有的情况下类,参数将不类人,只是构造函数参数的成员。编译器基本上是告诉你:哎,你说,那firstName和lastName的成员,其覆盖/重新定义从基类继承的东西 - 但并没有什么,只要我可以告诉...

class Person(val firstName: String, val lastName: String) 
class Employee(fn: String, ln: String, val salary: BigDecimal) extends Person(fn, ln) 

你不需要在这里声明firstName/lastName作为覆盖,顺便说一句。简单地将这些值转发给基类的构造函数就可以实现。

1

您也可以考虑重新设计超类的特性尽可能。例如:

trait Person { 
    def firstName: String 
    def lastName: String 
} 

class Employee(
    val firstName: String, 
    val lastName: String, 
    val department: String 
) extends Person 

甚至

trait Employee extends Person { 
    def department: String 
} 

class SimpleEmployee(
    val firstName: String, 
    val lastName: String, 
    val department: String 
) extends Employee