我来自Java背景,是Scala的新手,目前正在阅读“Scala编程”一书。
书中有一个例子如下:
class Rational(n: Int, d: Int) { // This won't compile
require(d != 0)
override def toString = n + "/" + d
def add(that: Rational): Rational = new Rational(n * that.d + that.n * d, d * that.d)
}
但是,鉴于此代码,编译器会抱怨:
error: value d is not a member of Rational
new Rational(n * that.d + that.n * d, d * that.d)
^
error: value n is not a member of Rational
new Rational(n * that.d + that.n * d, d * that.d)
^
error: value d is not a member of Rational
new Rational(n * that.d + that.n * d, d * that.d)
^
解释说:
虽然类参数n和d在add方法的代码中,但是只能在调用add的对象上访问它们的值。因此,当您在添加的实现中说n或d时,编译器很乐意为您提供这些类参数的值。但是它不会让你说那个.n或那个。因为它没有引用调用了add的Rational对象。要访问分子和分母,您需要将它们放入字段中。
同样正确的实施如下:
class Rational(n: Int, d: Int) {
require(d != 0)
val numer: Int = n
val denom: Int = d
override def toString = numer + "/" + denom
def add(that: Rational): Rational =
new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)
}
我多次尝试理解这一点,但仍然不清楚。
我已经在课程级别拥有n
和d
参数。我可以使用add
方法访问它们。我正在将另一个Rational
对象传递给add
方法。它也应该是n
和d
,对吧?
that.n
和that.d
有什么问题?为什么我需要在字段中获取参数?
此外,被覆盖的toString
方法只是采用n
和d
,这怎么会失败?
我可能听起来很愚蠢,但在我继续前进之前,确实需要清楚地理解这一点以获得更好的基本面。
答案 0 :(得分:6)
传递给类构造函数的参数默认为私有成员,因此可用于所有类代码(如toString
覆盖中所示),但它们不能作为实例成员访问(因此that.d
不起作用。)
您可以告诉编译器不要使用默认值。
class Rational(val n: Int, val d: Int) { // now it compiles
...
或者,传递给case class
的参数默认为实例成员。
case class Rational(n: Int, d: Int) { // this also compiles
...
答案 1 :(得分:2)
Scala具有比Java更多类型的访问修饰符。在Scala中有一个名为private[this]
的东西,意味着"私有的当前对象"这比普通private
更严格,这意味着"私有这个类的所有对象"。
class Rational(n: Int, d: Int)
与
基本相同class Rational(private[this] val n: Int, private[this] val d: Int)
在更高,几乎是哲学层面你可以说
class Rational(n: Int, d: Int) { ... }
就像一个返回Rational
的静态方法,它有参数n
和d
,并且在任何方法中它的参数都是方法的本地参数。通过使用val
或var
对参数进行限定,您可以将这些参数转换为Rational
的字段,而无需将它们写入两次:一次作为方法的参数(或构造函数,即这个静态方法的更具体的名称),以及一次作为字段。
答案 2 :(得分:0)
我正在读同一本书,我也有同样的疑问。当我反编译代码时,这就是生成的内容。
class Employee(var age: Int)
转译为
public class Employee {
private int age;
public int age() {
return this.age;
}
public void age_$eq(final int x$1) {
this.age = x$1;
}
public Employee(final int age) {
this.age = age;
super();
}
}
接下来,
class Employee(val age: Int)
转译为
public class Employee {
private final int age;
public int age() {
return this.age;
}
public Employee(final int age) {
this.age = age;
}
}
接下来,
class Employee(age: Int)
转译为
public class Employee {
public Employee(final int age) {
}
}
示例
class Employee(age: Int) {
def getAge(): Int = age
}
转译为
public class Employee {
private final int age;
public int getAge() {
return this.age;
}
public Employee(final int age) {
this.age = age;
}
}