Scala 声明和初始化实例/类变量的首选方式
在以下来自类或对象的代码片段中(我假定对这两个对象的处理类似): 我不相信我们会盲目地在所有情况下都放弃一个选择:Scala 声明和初始化实例/类变量的首选方式,scala,optional,Scala,Optional,在以下来自类或对象的代码片段中(我假定对这两个对象的处理类似): 我不相信我们会盲目地在所有情况下都放弃一个选择: private var consumer : Option[Consumer] = None def getConsumer(channel : Channel) = consumer.getOrElse( // build it consumer = Some(/* built val */) } 是的,上述情况很有
private var consumer : Option[Consumer] = None
def getConsumer(channel : Channel) = consumer.getOrElse(
// build it
consumer = Some(/* built val */)
}
是的,上述情况很有可能,但我的直觉是,还有其他选择。我很欣赏你的见解
编辑消费者对象直接发送到第三方api;因此,此处不可能对其进行需要更改签名的更改/修饰
以下是一个例子:
channel.basicConsume(queue, true, getConsumer(channel))
或
理想情况下,您希望在构造对象时初始化所有字段
lazy val
s提供在需要使用该值之前推迟初始化的选项。
在您的用例中,我建议将通道传递到构造函数中,并按如下方式使用它:
case class WithChannel(channel: Channel){
lazy val consumer = {create consumer, you can use channel here}
channel.basicConsume(queue, true, consumer)
}
如果在构造对象的其余部分时不可能始终具有通道,那么使用类来表示未初始化的情况可能会很有用
case class Uninitialised(someArg: Any){
def withChannel(channel: Channel) = Initialised(someArg, channel)
}
case class Initialised(someArg: Any, channel: Channel){
lazy val consumer = { some means of creating the consumer }
channel.basicConsume(queue, true, consumer)
}
val uninit = Uninitialised("Bob")
val init = uninit.withChannel(channel)
这样做的好处是有null
s,没有选项
s,对象的状态由其类型描述,而不是由其成员描述
您是否要使用
类
而不是案例类
class Initialised(someArg:Any, val channel: Channel)
注意
频道之前的val
。这使得channel
成为类的字段,而不仅仅是构造函数的参数。如果您希望在对象初始化之外使用它,例如在方法中和构造惰性VAL,则这是必需的。case类
es的参数是隐式的val
理想情况下,在构造对象时,您希望初始化所有字段lazy val
s提供在需要使用该值之前推迟初始化的选项。
在您的用例中,我建议将通道传递到构造函数中,并按如下方式使用它:
case class WithChannel(channel: Channel){
lazy val consumer = {create consumer, you can use channel here}
channel.basicConsume(queue, true, consumer)
}
如果在构造对象的其余部分时不可能始终具有通道,那么使用类来表示未初始化的情况可能会很有用
case class Uninitialised(someArg: Any){
def withChannel(channel: Channel) = Initialised(someArg, channel)
}
case class Initialised(someArg: Any, channel: Channel){
lazy val consumer = { some means of creating the consumer }
channel.basicConsume(queue, true, consumer)
}
val uninit = Uninitialised("Bob")
val init = uninit.withChannel(channel)
这样做的好处是有null
s,没有选项
s,对象的状态由其类型描述,而不是由其成员描述
您是否要使用类
而不是案例类
class Initialised(someArg:Any, val channel: Channel)
注意频道之前的val
。这使得channel
成为类的字段,而不仅仅是构造函数的参数。如果您希望在对象初始化之外使用它,例如在方法中和构造惰性VAL,则这是必需的。case类
es的参数是隐式的val
您试图重新创建的模式称为记忆化
val getConsumer = {
val cache = collection.mutable.Map.empty[Channel, Consumer]
(channel : Channel) => cache.getOrElseUpdate(channel, Consumer(channel))
}
值得一提的是,上面的假设是您在其构造函数中构建消费者
。否则,您可以使用您想要的任何功能,而不是消费者(频道)
此模式由许多Scala库包装,因此您可以依赖其中一个。例如,Scalaz。您试图重新创建的模式称为记忆化
val getConsumer = {
val cache = collection.mutable.Map.empty[Channel, Consumer]
(channel : Channel) => cache.getOrElseUpdate(channel, Consumer(channel))
}
值得一提的是,上面的假设是您在其构造函数中构建消费者
。否则,您可以使用您想要的任何功能,而不是消费者(频道)
此模式由许多Scala库包装,因此您可以依赖其中一个。例如,Scalaz。这看起来像是您试图重新创建惰性val
功能。也许看看是怎么做到的。谢谢你的提示。我现在正在研究lazy val(你是对的,我对它们不太熟悉)@ggovan我们如何处理lazy val的通道参数?从代码的外观来看,消费者
只为第一个通道
设置了一次。在这种情况下,channel
应该是构造函数的参数。这当然取决于您的用例。@ggovan是的,我同意,但在我的小调查中,不清楚如何为lazy val提供构造函数/参数。您是否可以提供一个正式的答案来说明如何做到这一点?看起来您正在尝试重新创建lazy val
功能。也许看看是怎么做到的。谢谢你的提示。我现在正在研究lazy val(你是对的,我对它们不太熟悉)@ggovan我们如何处理lazy val的通道参数?从代码的外观来看,消费者
只为第一个通道
设置了一次。在这种情况下,channel
应该是构造函数的参数。这当然取决于您的用例。@ggovan是的,我同意,但在我的小调查中,不清楚如何为lazy val提供构造函数/参数。您是否可以提供一个正式的答案来说明如何做到这一点?您显然为此付出了大量的思考和努力。不清楚这如何直接帮助特定用例:我需要一个消费者对象。你表演的课程有点像舞蹈。例如,WithChannel:这不是消费者的替代品。。它是?请考虑调用消费者(消费者)的一些方法。然后显示您的构造如何满足该签名。@javadba您能否扩展问题中的示例,显示getConsumer
所在的类及其使用方式(或简化版本),然后我将在回答中包含该类。我展示的课程就是这个课程。看起来你在设计一个手臂式的模式。我不是真的在这里找。不希望更改调用外部类的签名:事实上,它是第三方java库。@javadba我不建议更改使用者,而是建议更改生成它的位置。例如,类上有getConsumer
方法