是否存在需要为类创建伴生对象(单例)的情况?为什么我要创建一个名为Foo
的类,并为其创建一个伴生对象呢?
是否存在需要为类创建伴生对象(单例)的情况?为什么我要创建一个名为Foo
的类,并为其创建一个伴生对象呢?
伴生对象基本上提供了一个地方,可以放置“类似静态”的方法。此外,伴生对象或伴生模块可以完全访问类成员,包括私有成员。
伴生对象非常适合封装工厂方法等内容。不必在各处都有Foo
和FooFactory
之类的东西,您可以使一个类及其伴生对象承担工厂职责。
伴生对象非常有用,可以存储对所有类实例通用的状态和方法,但它们不使用静态方法或字段。它们使用常规的虚拟方法,这些方法可以通过继承进行覆盖。Scala 确实没有任何静态元素。你可以用很多种方式使用它,但这里是一个简单的示例。
abstract class AnimalCounter
{
var animals = 0
def name: String
def count()
{
animals += 1
println("%d %ss created so far".format(animals, name))
}
}
abstract class Animal
{
def companion: AnimalCounter
companion.count()
}
object Dog extends AnimalCounter
{
val name = "dog"
}
class Dog extends Animal
{
def companion = Dog
}
object Cat extends AnimalCounter
{
val name = "cat"
}
class Cat extends Animal
{
def companion = Cat
}
这将产生以下输出:
scala> new Dog
1 dogs created so far
scala> new Cat
1 cats created so far
scala> new Dog
2 dogs created so far
scala> new Cat
2 cats created so far
这是一个很好的存储静态工厂方法(不是设计模式)的地方,用于配合类。如果您将那些重载的工厂方法命名为apply(/.../),则可以创建/初始化您的类:
无需使用'new'关键字(并不是非常重要)
具有不同可能参数集(与Bloch在Effective Java中关于望远构造器所述的相比较)
能够决定要创建哪个派生类而不是抽象(附带的)类
示例代码:
abstract class AbstractClass;
class RealThing(s: String) extends AbstractClass;
class AlternativeThing(i: Int) extends AbstractClass;
object AbstractClass {
def apply(s: String) = {
new RealThing(s)
}
def apply(i: Int) = {
new AlternativeThing(i)
}
}
// somewhere else you can
val vs = AbstractClass("asdf") // gives you the RealThing wrapped over string
val vi = AbstractClass(123) // gives you AlternativeThing wrapped over int
我不会把对象/基类称为AbstractXxxxx,因为它看起来并不好:就像创建一些抽象的东西。给这些名称赋予真正的含义。考虑使用不可变、没有方法的case类,并封闭抽象基类。
RealThing
and AlternativeThing
class should have a private
constructor to force the user to use the AbstractClass
has factory.
class AlternativeThing private(i: Int) extends AbstractClass
- metch如第1章所述,Scala比Java更面向对象的一种方式是Scala类不能有静态成员。相反,Scala有单例对象(第65页)。
首先,它清晰地区分了静态方法和非静态方法。同时提供了创建单例类的简单方式。
它还可以继承其他类和/或特质的方法,这是Java静态方法无法实现的,并且可以作为参数传递。