代码之家  ›  专栏  ›  技术社区  ›  Daniel Martin

scala 2.10“无隐式视图可用”请求视图的类型参数错误

  •  3
  • Daniel Martin  · 技术社区  · 6 年前

    我已经将这个例子从一个更大的项目中遇到的问题中减少了;基本的问题似乎是scala 2.10对视图约束的处理有点奇怪,或者可能会中断:

    trait Nameish {
      def name: String
    }
    
    abstract class Namer[A <% Nameish](e: Class[A]) {
      def doNameThing(x: A) = println("argument is named " + x.name)
    }
    class SubNamer[A <% Nameish](e: Class[A]) extends Namer(e) {
    }
    
    object TestViews extends App {
      import scala.language.implicitConversions
      implicit def nameStr(x: String): Nameish = new StringNamer(x);
    
      class StringNamer(x: String) extends Nameish {
        def name = x
      }
    
      println(new SubNamer(classOf[String]).doNameThing("foo"))
    }
    

    当我试图编译这个时,在scala 2.10中我得到了错误:

    TestViews.scala:8: error: No implicit view available from A => Nameish.
    class SubNamer[A <% Nameish](e: Class[A]) extends Namer(e) {
                     ^
    TestViews.scala:18: error: value doNameThing is not a member of SubNamer[String]
      println(new SubNamer(classOf[String]).doNameThing("foo"))
                                            ^
    two errors found
    

    请注意,scala 2.11可以使用此代码。

    不幸的是,将此代码重新工具化到较新的scala版本将使此任务的规模激增。我需要找到一种方法,使现有的scala接受具有视图约束的类型参数的类层次结构。


    另一种解决方法发现了不同的scala-2.10错误案例:

    trait Nameish {
      def name: String
    }
    
    abstract class Namer[A](e: Class[A])(implicit view: A => Nameish) {
      def doNameThing(x: A) = println("argument is named " + x.name)
    }
    class SubNamer[A](e: Class[A])(implicit view: A => Nameish) extends Namer(e)(view) {
    }
    
    object TestViews extends App {
      import scala.language.implicitConversions
      implicit def nameStr(x: String): Nameish = new StringNamer(x);
    
      class StringNamer(x: String) extends Nameish {
        def name = x
      }
    
      println(new SubNamer(classOf[String]).doNameThing("foo"))
    }
    

    这只是用隐式参数替换视图约束。

    使用这段代码,它再次可以很好地编译scala 2.11,但是在scala 2.10上:

    TestViews.scala:8: error: `implicit' modifier cannot be used for top-level objects
    class SubNamer[A](e: Class[A])(implicit view: A => Nameish) extends Namer(e)(view) {
                                            ^
    one error found
    

    我不明白这里发生了什么:我不是要声明一个隐式对象,我是要声明类接受一个隐式参数。为什么一等舱可以,而二等舱不行?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Yuval Itzchakov    6 年前

    添加参数类型参数 A Namer (在 Subnamer 继承)为我工作(scala版本2.10.7):

    class SubNamer[A <% Nameish](e: Class[A]) extends Namer[A](e)
    

    顺便说一句,您的没有修改的示例仅在scala版本2.11.5中对我有效。

    希望这有帮助。