Java Scala:类参数访问与对象字段访问
我来自Java背景,刚接触Scala,目前正在阅读《Scala编程》一书 书中有一个例子如下:Java Scala:类参数访问与对象字段访问,java,scala,class,parameters,field,Java,Scala,Class,Parameters,Field,我来自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) }
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)
}
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
)
}
但是,鉴于此代码,编译器会抱怨:
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的对象上访问它们的值。因此,当您在add的实现中说n或d时,编译器很乐意为您提供这些类参数的值。但它不允许您说.n或.d,因为它不引用调用add的Rational对象。要访问上面的分子和分母,需要将它们放入字段中
下面给出了正确的实现方法:
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)
}
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
,这怎么不失败呢
我可能听起来很愚蠢,但在我继续之前,我确实需要清楚地理解这一点,以便更好地了解基本原理。传递给类构造函数的参数默认为私有成员,因此可用于所有类代码(如
toString
覆盖中所示),但它们不能作为实例成员访问(因此,说明.d
不起作用)
您可以告诉编译器不要使用默认值
class Rational(val n: Int, val d: Int) { // now it compiles
...
或者,传递给案例类的参数默认为实例成员
case class Rational(n: Int, d: Int) { // this also compiles
...
Scala比Java有更多类型的访问修饰符。在Scala中有一种叫做private[this]
的东西,它意味着“对当前对象私有”,比普通的private
更严格,后者意味着“对这个类的所有对象私有”
基本上与
class Rational(private[this] val n: Int, private[this] val d: Int)
从更高的、近乎哲学的角度来看,你可以这么说
class Rational(n: Int, d: Int) { ... }
就像一个静态方法返回一个Rational
,它有参数n
和d
,并且在任何方法中,它的参数都是方法的局部参数。通过使用val
或var
限定参数,您可以将这些参数转换为Rational
的字段,而不必将它们写入twice:一次作为方法的参数(或构造函数,这是此静态方法更具体的名称),一次作为字段