我写了以下代码:
class a {
object c {
var a = "STATIC"
def m() = print("STATIC METHOD")
var f = () => print("STATIC FUNCTION")
}
}
object m {
def main(args: Array[String]) = {
var o = new a()
o.c.m()
}
}
c
中声明的变量,函数和方法可以是静态的吗?c
更改对象a
的名称,那么该对象会成为伴侣对象吗?答案 0 :(得分:3)
object
中的字段和方法是Scala如何在Java中声明您将使用static
的内容。我想你可以直觉地说那些字段通常是static
(就像在中只有一个JVM中的一个)。
但是,在您的示例中,您在类中放置了object
,使其不再是 static 。您可以使用几行代码轻松检查(您可以找到here on Scastie)。
class MyClass {
object Embedded {
val a = "field"
def m = println("method")
}
}
val a = new MyClass().Embedded
val b = new MyClass().Embedded
// prints "a and b are different objects"
if (a eq b)
println("a and b are the same object")
else
println("a and b are different objects")
关于您的第二个问题:不,class
和object
必须位于同一范围内,才能使其成为伴侣对象。您可以在Scala Language Specification上找到更多详细信息。
我引用那里:
通常,类的伴随模块是一个与该类同名的对象,并在同一范围和编译单元中定义。相反,该类被称为模块的伴随类。
答案 1 :(得分:3)
Scala与Java没有“静态”的真正含义。
对象在使用静态方法/字段的JVM上有支持这一事实是一个泄漏的实现细节,如果使用Java / JVM互操作,您只需要处理它。
除非你明确需要这个互操作,否则你需要停止将声明的对象视为'静态',而是将它们视为在给定范围内的单例。
嵌套在类下的内部对象意味着对于每个类实例,只有1个实例,不同于可能有多个实例的内部类。
这也适用于顶级,除了Scala可以与其他JVM语言进行额外兼容,并将某些方法/成员标记为静态。
答案 2 :(得分:2)
回答你的问题:
a.c
中的方法和字段不是全局静态的,因为它们需要存在a
的实例。如果a
是对象,a.c
也是静态的。
如果您想要一个包含静态字段和方法的伴随对象a
,则必须在a
的代码块之外定义它,如下所示:
class a {
/* non-static stuff goes here */
}
object a {
/* static stuff goes there */
def m() = print("STATIC METHOD")
}
您必须将两者保存在同一个文件中,定义对象或
class first无关紧要,因此它通常取决于约定或根据用例最有意义。
如果您想在a.m
内调用静态方法class a
,则仍需要将其称为a.m
,而不仅仅是m
。但是class a
将能够使用object a
的私有字段和方法,因为它们是同伴。
正如其他人已经说过的那样,static
在Scala中并不存在,但是这个概念来自Java,因为Scala在大多数情况下被编译成java字节码。
最后的建议,Scala和Java中的类和对象的约定通常是相同的:它们的名字的第一个字母应该是大写的(除了一些高级的Scala案例)