【问题标题】:Implementing fields in Scala generic classes在 Scala 泛型类中实现字段
【发布时间】:2018-06-24 12:38:44
【问题描述】:

我需要一些有关 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 generics types abstract


    【解决方案1】:

    您需要在实现中定义实际类型。看看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")
    }
    

    当然,您可以指定特征本身以获得更通用的配置(参见上面的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)
    }
    

    【讨论】:

    • 谢谢 :) 我有没有办法在不明确定义类型的情况下实现这些 Config 类?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-14
    • 1970-01-01
    相关资源
    最近更新 更多