奥德斯基的说法是正确且有意义的,但有些人不明白他的意思。
假设在 Java 中你有一个带有方法 f 的 Foo 类:
class Foo {
int f() { /* does something great */ }
}
您可以编写一个接受 Foo 并在其上调用 f 的方法:
void g(Foo foo) { foo.f(); }
也许有一个类 SubFoo 扩展了 Foo; g 也适用于此。可以有一整套类,通过继承或接口相关,它们共享可以与 g 一起使用的事实。
现在让我们创建 f 方法static:
class Foo {
static int f() { /* does something great */ }
}
我们可以像这样将这个新的 Foo 与 g 一起使用吗?
g(Foo); // No, this is nonsense.
该死。好的,让我们更改 g 的签名,以便我们可以将 Foo 传递给它并让它调用 f。
哎呀——我们不能。我们无法传递对 Foo 的引用,因为Foo 不是某个类的实例。一些在这里评论的人对有一个与 Foo 对应的 Class 对象这一事实感到困惑,但正如 Sotirios 试图解释的那样,该 Class 对象没有 f 方法,并且 Foo 不是该类的实例。 Foo 不是任何事物的实例;它根本不是一个物体。 Foo 的 Class 对象是 Class 类的一个实例,它具有有关 Foo 的信息(将其视为 Foo 的内部维基百科页面),并且是完全不相关进行讨论。维基百科上的“老虎”页面并不是老虎。
在 Java 中,像 3 和 'x' 这样的“基元”不是对象。他们areScala 中的对象。为了提高性能,您的程序将在执行过程中尽可能使用 JVM 原语 3 和“x”,但在您编写代码的级别上,它们实际上是对象。事实是他们是not对于任何试图编写处理所有数据类型的代码的人来说,Java 中的对象都会带来相当不幸的后果——您必须有特殊的逻辑和附加方法来覆盖原语。如果您曾经见过或编写过此类代码,您就会知道它很糟糕。奥德斯基的说法并不是“纯粹主义”;而是“纯粹主义”。离得很远。
在 Scala 中,没有任何运行时数据不是对象,也没有任何可以调用非对象方法的东西。在 Java 中,这些陈述都不是真的; Java 是一种部分面向对象的语言。在Java中,有些东西不是对象,有些方法不是对象上的。
Scala 新手经常会想到object Foo
作为 Java 静态的一些奇怪的替代品,但这是你需要快速克服的东西。相反,将 Java 的静态方法视为非 OO 疣,而将 Scala 的静态方法视为非 OO 疣。object Foo { ... }
沿着这些思路:
class SomeHiddenClass { ... }
val Foo = new SomeHiddenClass // the only instance of it
这里 Foo 是一个value, not a type,它确实是一个对象。它可以传递给一个方法。它可以扩展一些其他类。例如:
abstract class AbFoo { def f:Int }
object Foo extends AbFoo { def f = 2 }
现在,你终于可以说
g(Foo)
确实,类的“伴生对象”是放置该类的非实例方法和数据的好地方。但该伴生对象是一个对象,因此通常的规则和功能适用。
事实上,在 Java 中,您将此类方法放在非对象上(限制它们的使用方式),这是一种负担,而不是一种功能。肯定是not OO.