是否存在需要用于类的伴侣对象(单例)的情况?为什么我要创建一个类,说一个,Foo
并为其创建一个伴随对象?
是否存在需要用于类的伴侣对象(单例)的情况?为什么我要创建一个类,说一个,Foo
并为其创建一个伴随对象?
Answers:
伙伴对象对于存储类的所有实例共有的状态和方法很有用,但它们不使用静态方法或字段。他们使用可以通过继承重写的常规虚拟方法。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
...这是一个为伴随的类存储静态工厂方法(不是DP)的好地方。如果您将那些重载的工厂方法命名为apply(/ ... /),则可以创建/初始化您的类
没有“新”(不是那么重要)
具有不同的可能参数集(与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,因为它看起来并不糟糕:就像创建抽象的东西一样。给那些名字一个真实的含义。考虑使用不可变,较少方法的案例类,并密封抽象基类。
RealThing
和AlternativeThing
类应具有一个private
构造函数,以强制用户使用AbstractClass
has工厂。class AlternativeThing private(i: Int) extends AbstractClass
我总是把伴侣当作桥梁在Scala中编写功能代码和面向对象代码。很多时候,我们只需要纯函数即可接受一些输入并提供处理结果。将这些相关函数放在伴随对象中,对于我自己以及在我的代码之上的一个建筑物而言,都易于查找和使用。
此外,它是一种语言提供的功能,无需执行任何操作即可编写单例模式。当您需要一个单身来封装JVM生命周期的委托者时,这特别有用。例如,在Scala中编写一个简单的HTTP客户端库,您可以在其中封装基于底层Java实现的委托人,并使API的使用者生活在纯净的世界中。