gpt4 book ai didi

scala - 在方法签名中引用枚举值类型

转载 作者:行者123 更新时间:2023-12-01 00:03:43 25 4
gpt4 key购买 nike

我想向 scala.Enumeration 添加一个方法。我的第一个方法是尝试扩展它,但被 this 咬了.我的第二种方法是尝试定义一个方法,并传入 Enumeration - 如果可行,我希望使用隐式转换。但是,我很难用方法的返回类型来保留类型。

object EnumExample {
object SampleEnum extends Enumeration {
val include, exclude = Value
}

def parse[T <: Enumeration](name:String, enum:T):T#Value =
enum.valueOf(name) match {
case Some(x) => x
case x => throw new RuntimeException("No field named '" + name + "' found on enum " + enum + ", legal values = " + enum.values)
}

def main(args:Array[String]) = {
//compiles fine, and preserves custom type
val withNameExample:SampleEnum.Value = SampleEnum.withName("include")

//also fine, but we lost type info
val enumWithHash:Enumeration#Value = parse("include", SampleEnum)

/**
error: type mismatch;
found : Main.$anon.EnumExample.SampleEnum#Value
required: Main.$anon.EnumExample.SampleEnum.Value
val parseExample:SampleEnum.Value = parse("include", SampleEnum)
*
*/
val customTypeWithHash:SampleEnum.type#Value = parse("include", SampleEnum)

//same error
val customTypeWithDot:SampleEnum.Value = parse("include", SampleEnum)
}
}

一个明显的解决方法是从 parse 方法中删除返回类型声明,但这给了我一个“非法的依赖方法类型”。这给我留下了很多问题:
  • 这可以指定吗?以一种或另一种方式,我想在解析字符串中的枚举字段时收到一条很好的错误消息。
  • 为什么我会得到“非法依赖方法类型”?
  • 在这种情况下,“#”运算符(?)究竟是什么?
  • 最佳答案

    这对我来说看起来像是一个错误(至少在我测试过的 2.8.0 Beta1 中)。

    特别有启发意义的是以下几点:

    scala> var x: SampleEnum.type#Value = null
    x: SampleEnum.Value = null

    在这里,我们请求的是任意的内部类型,但我们实际上获得了特定的内部类型。那只是坏了(如果还没有错误报告,我会提交一份错误报告,除非其他人迅速解释为什么这不是错误)。

    那么该怎么办?好吧,首先我们来了解一下parse的原始方法签名:
    def parse[T <: Enumeration](name:String, enum:T):T#Value

    我们有 T这是 Enumeration 的子类, enum这是 T 的一个实例,和--因为没有办法表达 Value必须来自 T 的特定实例,我们不得不求助于 T#Value (即 T 的内部类型,而不考虑它来自哪个特定的 T)。

    现在我们必须传入一个特定的对象,取回一个通用的内部对象,然后面对 ExampleObject.type#Value 做这件事。与 ExampleObject.Value 相同即使它们的类型不同。

    所以我们必须从头开始编写我们自己的对象:
    class SampleWorkaroundClass extends Enumeration {
    val include, exclude = Value
    }
    lazy val SampleWorkaround = new SampleWorkaroundClass

    这里我们有一个特殊定义的类的单个实例。现在我们可以绕过 Object 中的错误:
    scala> val typeWorks:SampleWorkaroundClass#Value = parse("include",SampleWorkaround)
    typeWorks: SampleWorkaroundClass#Value = include

    ( lazy val 只是为了获得与在使用之前不会实例化的对象完全相同的行为;但单独使用 val 就可以了。)

    编辑: Outer#Inner表示“来自该外部类的任何类型为 Inner 的内部类”,而不是 myOuter.Inner这意味着“只有类型为 Inner 的类具有 OutermyOuter 的实例作为其封闭类”。另外,我在 2.8.0 Beta1 中没有遇到依赖类型错误——但是无法指定类型让事情变得很尴尬。

    编辑:更新错误报告——它现在的工作方式显然是故意的。要以这种方式使用类型,您打算在函数调用中显式指定类型(因为它不会被推断为您想要的),就像这样
    val suggested: SampleEnum.type#Value = parse[SampleEnum.type]("include",SampleEnum)

    如果您只需要这样做几次,这种方法会更容易。如果您必须多次这样做,使用 val(或惰性 val)实例化创建自己的类可能会使事情变得更容易/更紧凑。

    关于scala - 在方法签名中引用枚举值类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2364555/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com