在scala中,如何使抽象类型的内部类型对不同实例保持不变?

三叶虫

在某些情况下,我想使用内部类型作为泛型类型的替代品,例如在以下情况下Dependent[T <: BaseType],我没有定义 ,而是这样定义它:

abstract class BaseType {

  type N
  def create(v: Int): N

  class Dependent(val n: N) {

    def +(other: Dependent) = new Dependent(create(n.hashCode() + n.hashCode()))
  }
}

object BaseType {

  class Aggregator[T <: BaseType](val seq: Seq[T#Dependent]) {

    def result() = seq.reduce(_ + _)
  }
}

显然这不会编译,因为Dependent现在是一个 Inner 类,并且Dependent在不同的 BaseType 实例下创建的不同,彼此不能互操作。(BTW 会抛出以下编译错误)

Error:(15, 35) type mismatch;
 found   : T#Inner
 required: _33.Inner where val _33: T
    def result() = seq.reduce(_ + _)

然而这个问题在scala中应该有一个简单的解决方案,因为在java中这样的任务可以通过以下方式轻松完成:

static class Dependent { ...

在 Scala 中拥有比 java 更长的代码是没有意义的。scala 中的一个直接类比是在 BaseType 中添加一个强制规则,这要求其所有实现都是对象/单例而不是类。但是我还没有看到这样的功能。

所以问题是,在java中可以轻松完成的相同事情的最短方法是什么?

UPDATE显然我不太清楚我的意图,我想要的不是Dependent按原样使用类,而是扩展 BaseTypeBaseType作为 的类型参数Dependent,例如,如果我定义了 2 个对象:

  object Sub1 extends BaseType {
    override type N = Long
    override def create(v: Int): N = v.toLong
  }
  object Sub2 extends BaseType {
    override type N = Double
    override def create(v: Int): N = v.toDouble
  }

然后+Aggregator如果它们来自同一个对象,则两者都可以用于 2 Dependent,这意味着这将成功:

  assert(
    new Aggregator(
      Seq(
        new Sub1.Dependent(1),
        new Sub1.Dependent(2)
      )).result() == new Sub1.Dependent(1) +
      new Sub1.Dependent(2)
  )

但这会失败:

  assert(
    new Aggregator(
      Seq(
        new Sub1.Dependent(1),
        new Sub2.Dependent(2)
      )).result() == new Sub1.Dependent(1) +
      new Sub2.Dependent(2)
  )

因为 2 个 Dependent 实例的类型不同,但是使用最新的 scala 编译器,即使第一个编译器也会失败,因为在定义 Aggregator 时,它不知道T <: BaseType是单例。

阿列克谢·罗曼诺夫

因为在 Java 中,可以通过以下方式轻松完成此类任务:

static class Dependent { ...

不,它没有完成任务,因为 thisDependent不能使用N(即使它是 的类型参数BaseType)。你需要static class Dependent<N>,Scala 等价物是

object BaseType {
  class Dependent[N]
}

如果您还没有伴随对象,这确实比 Java 稍长,但在 Scala 设计中,它并不要求它可以用更短的代码完成 Java 可以做的任何事情(或者根本没有,真的)。

如果你想

然后 + 符号和聚合器都可以用于 2 Dependent 仅当它们来自同一个对象时,这意味着这将成功

这可以做到:

class Aggregator[T <: BaseType with Singleton](val seq: Seq[T#Dependent]) {
  def result() = seq.reduce(_ + _)
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在Scala中反映与抽象类型的类型参数相对应的具体类型?

来自分类Dev

Scala抽象类型成员

来自分类Dev

Scala 中的抽象类型、变量和类型类

来自分类Dev

如何在外部类中声明实例变量(内部类类型)?

来自分类Dev

如何在C#中对具有抽象内部类型的泛型进行模式匹配?

来自分类Dev

如何返回抽象类型?

来自分类Dev

R中的抽象类型

来自分类Dev

Scala中通用抽象类型的模式匹配

来自分类Dev

Scala中具有抽象类型的F界多态

来自分类Dev

PyXB:无法实例化抽象类型

来自分类Dev

如何对抽象类型使用类型约束

来自分类Dev

Scala:使用类型参数或抽象类型作为类型界限

来自分类Dev

如何在Scala中创建通用列表monoid来维护所涉及列表的内部类型?

来自分类Dev

如何在AGDA中定义抽象类型

来自分类Dev

如何在AGDA中定义抽象类型

来自分类Dev

如何获取模板类型的内部类型?

来自分类Dev

如何在Scala中实例化Java通用内部类?

来自分类Dev

Scala:比较内部类对象的类型

来自分类Dev

Scala抽象类型成员-继承和类型界限

来自分类Dev

具有返回不同类型子项的抽象类中的C#抽象方法

来自分类Dev

理解抽象类型

来自分类Dev

如何使用抽象类型合并?

来自分类Dev

MXBean操作签名中的抽象类型

来自分类Dev

返回抽象类中的具体类型

来自分类Dev

Julia中抽象类型数组的用法

来自分类Dev

在C ++中声明抽象类型的变量

来自分类Dev

python中的抽象类:强制类型

来自分类Dev

如何在Java内部类中定义绑定类型参数

来自分类Dev

抽象类作为类型,派生类作为实例在C ++中