2015-12-30 26 views
1

从Scala食谱中可以看出,如果构造函数变量没有用'var'或'val'定义,那么默认情况下Scala不会生成访问器和修饰符方法,但是在下面的例子。覆盖访问器和mutator方法覆盖

1. class Person2(name : String) { 
2. def name = name; 
3. def name_=(aName : String) {name = aName} 
4. } 

我正在一个编译时在第2行的“重载方法名称需要结果类型”。这是什么意思?我是否重载了名称访问器方法,但是从Cookbook中不会生成访问器和增变器方法。请任何人回答这个问题。

回答

0

Scala编译器在这里被函数和类参数的同名所困惑。这个例子的工作原理:

所有的
scala> class Person2(aName : String) { 
    | def name = aName 
    | def name_=(name : String) {aName = name} 
    | } 
defined class Person2 
+0

但是为什么要混淆,因为在这里我已经给出了构造函数参数的存取方法,即使方法名称与参数名称相同但都指向相同的东西。 –

+0

你在'mutator'中混合了'name'和'aName'。试试这个:'new Person2(“foo”)。name =“bar”'看看它有多壮观:) – Dima

+0

@Clashsoft编辑过的版本不能编译:''reassignment to val' – Dima

1

首先,注意,class Foo(bar: String)没有定义命名bar一个成员变量,只有一个构造函数的参数。 您仍然可以在类的任何地方使用它,因为整个类定义都在构造函数体内,所以它本质上是一个闭包,但是您将无法为其指定值。因此,如果我们在前面的答案中修复了错字

class Person2(aName : String) { 
    def name = aName 
    def name_=(aName : String) = { aName = name } 
} 

这将失败,并显示消息“重新分配给val”。 这是因为aName这里只是一个函数(构造函数)参数,并且所有参数始终是不可变的,您不能指定给它们。

此外,如果您尝试new Person2("foo").aName,它也会失败,因为aName不是Person2的成员。

现在,你的问题。与java不同,scala中的方法和变量在同一个命名空间中,所以你不能同时拥有一个名字相同的变量和方法。这就是你遇到的编译错误。

当你写class Person2(val name: String),你得到的是在生成JVM类中定义的私有最后一个变量name,这不是在Scala中直接访问和方法name(),返回值是。

当您编写class Person2(var name: String)时,您将再次获得私有(而非最终)JVNM类成员以及两个用于访问其值的scala方法。

因此,您提到的食谱中的“访问器方法”指的是访问底层JVM类成员的值,而不是实际定义的Scala类。

最后,当你做class Person2(name: String)你根本没有创建任何类的成员,所以没有什么可以访问。