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
方法