scala - 在 Scala 泛型类中实现字段
问题描述
我需要一些有关 Scala 通用特征的帮助。
我有一个带有返回类型 T 的方法的类。在我的类的每个实现中,我想返回一个可以使用的 T 的子类。
基本上,在我的抽象类中,我需要一个返回 Configs 对象的方法,并且每个实现都有自己的 Configs 对象实现。另外,我想用另一个抽象类子类化抽象类,更加限制这个 Configs 对象(原始 Configs 对象的子类)。无论我做什么,都会出现编译错误。
这是我尝试过的:
case class MyConfigs()
trait WithMyConfigs {
def myConfigs: MyConfigs
}
case class LimitConfigs(myConfigs: MyConfigs, limit: Int) extends WithMyConfigs
case class TextConfigs(myConfigs: MyConfigs, text: String) extends WithMyConfigs
trait AbstractClass {
def configs[B <: WithMyConfigs]: B
}
class ImplLimitClass extends AbstractClass {
override def configs[B <: WithMyConfigs]: B = LimitConfigs(MyConfigs(), 5)
}
class ImplSizeClass extends AbstractClass {
override def configs[B <: WithMyConfigs]: B = TextConfigs(MyConfigs(), "test")
}
trait WithRestrictedConfigs extends WithMyConfigs {
def additionalIntField: Int
}
trait RestrictedAbstractClass extends AbstractClass {
override def configs[B <: WithRestrictedConfigs]: B
}
case class RestrictedConfigs(myConfigs: MyConfigs, additionalIntField: Int) extends WithRestrictedConfigs
class ImplRestrictedClass extends RestrictedAbstractClass {
override def configs[B <: WithRestrictedConfigs]: B = RestrictedConfigs(MyConfigs(), 5)
}
这样我得到错误'TextConfigs/LimitConfigs 类型的表达式不符合预期的 B 类型'。
我还尝试了以下方法:
case class MyConfigs()
trait WithMyConfigs {
def myConfigs: MyConfigs
}
case class LimitConfigs(myConfigs: MyConfigs, limit: Int) extends WithMyConfigs
case class TextConfigs(myConfigs: MyConfigs, text: String) extends WithMyConfigs
trait AbstractClass {
type B <: WithMyConfigs
def configs: B
}
class ImplLimitClass extends AbstractClass {
override def configs: B = LimitConfigs(MyConfigs(), 5)
}
class ImplSizeClass extends AbstractClass {
override def configs: B = TextConfigs(MyConfigs(), "test")
}
trait WithRestrictedConfigs extends WithMyConfigs {
def additionalIntField: Int
}
trait RestrictedAbstractClass extends AbstractClass {
override type B <: WithRestrictedConfigs
override def configs: B
}
case class RestrictedConfigs(myConfigs: MyConfigs, additionalIntField: Int) extends WithRestrictedConfigs
class ImplRestrictedClass extends RestrictedAbstractClass {
override def configs: B = RestrictedConfigs(MyConfigs(), 5)
}
然后我得到“XXX 类型的表达式不符合预期的 ImplRestrictedClass.this.B 类型”。
如果有人知道如何提供帮助,那就太好了:)
解决方案
您需要在实现中定义实际类型。看看scala-doc。
这是一个编译的例子:
case class MyConfigs()
trait WithMyConfigs {
def myConfigs: MyConfigs
}
case class LimitConfigs(myConfigs: MyConfigs, limit: Int) extends WithMyConfigs
case class TextConfigs(myConfigs: MyConfigs, text: String) extends WithMyConfigs
trait AbstractClass {
type T <: WithMyConfigs
def configs :T
}
class ImplLimitClass extends AbstractClass {
type T = LimitConfigs
override def configs: T = LimitConfigs(MyConfigs(), 5)
}
class ImplSizeClass extends AbstractClass {
type T = TextConfigs
override def configs: T = TextConfigs(MyConfigs(), "test")
}
trait WithRestrictedConfigs extends WithMyConfigs {
def additionalIntField: Int
}
trait RestrictedAbstractClass extends AbstractClass {
type T <: WithRestrictedConfigs
override def configs: T
}
case class RestrictedConfigs(myConfigs: MyConfigs, additionalIntField: Int) extends WithRestrictedConfigs
class ImplRestrictedClass extends RestrictedAbstractClass {
type T = RestrictedConfigs
override def configs: T = RestrictedConfigs(MyConfigs(), 5)
}
[更新]
您需要在某处指定您的类型。如果使用类型参数,您将得到如下信息:
trait AbstractClass[T <: WithMyConfigs] {
def configs: T
}
class ImplLimitClass extends AbstractClass[LimitConfigs] {
override def configs = LimitConfigs(MyConfigs(), 5)
}
class ImplSizeClass extends AbstractClass[WithMyConfigs] {
override def configs = TextConfigs(MyConfigs(), "test")
}
当然,您可以指定 trait 本身以获得更通用的配置(见ImplSizeClass
上文),然后使用额外的 trait 隐藏类型参数。
trait SpecAbstractClass extends AbstractClass[WithMyConfigs]
如果您不想指定显式类型,为什么不使用老式的接口使用方式:
case class MyConfigs()
trait WithMyConfigs {
def myConfigs: MyConfigs
}
case class LimitConfigs(myConfigs: MyConfigs, limit: Int) extends WithMyConfigs
case class TextConfigs(myConfigs: MyConfigs, text: String) extends WithMyConfigs
trait AbstractClass {
def configs: WithMyConfigs
}
class ImplLimitClass extends AbstractClass {
override def configs = LimitConfigs(MyConfigs(), 5)
}
class ImplSizeClass extends AbstractClass {
override def configs = TextConfigs(MyConfigs(), "test")
}
trait WithRestrictedConfigs extends WithMyConfigs {
def additionalIntField: Int
}
trait RestrictedAbstractClass extends AbstractClass {
override def configs: WithRestrictedConfigs
}
case class RestrictedConfigs(myConfigs: MyConfigs, additionalIntField: Int) extends WithRestrictedConfigs
class ImplRestrictedClass extends RestrictedAbstractClass {
override def configs = RestrictedConfigs(MyConfigs(), 5)
}
推荐阅读
- javascript - URL 哈希:目标在 ajax 元素上
- c# - 防止从外部类 c# 访问列表元素
- r - 无法在 R 4.0.1 中安装包 tidyverse
- azure-iot-edge - 如何为 100 多个边缘设备配置单个模块
- python - 如何在招摇领域添加示例
- flutter - 如何在颤振中创建自定义工具栏?
- flutter - 如何在颤动的列表视图中设置卡片的宽度?
- javascript - 如何存储从 API 检索的值并在整个应用程序中使用它
- windows - 如何隐藏 tcp 端口侦听器 powershell 脚本?
- javascript - Vue.js:无法从云 Firestore 中检索数据