scala – 如何在编译时进行类型检查?

TraversableOnce中,有一个sum方法只有在包含的类型是Numeric时才可用(否则它将不会编译).我想知道这是否可用于其他情况(以避免运行时检查).

特别是我们有两个特征A和B的情况.我们希望有一个方法f,只有当对象继承A和B时才能使用.但是如果它只扩展其中一个,则不会.我不想做另一个特征AB扩展A与B.我只是想要无法使用f,如果不是两个特征都被继承.

package com.example

trait Base
trait Foo extends Base {
  def g = println("foo bar " + toString)
}
trait Bar extends Base {
  /* If this is both Foo and Bar,I can do more */
  def f = {
    if (!this.isinstanceOf[Foo]) error("this is not an instance of Foo")
    this.asInstanceOf[Foo].g
  }
}
object Test {
  def main(args: Array[String]): Unit = {
    object ab extends Foo with Bar
    object ba extends Bar with Foo
    object b extends Bar
    ab.f
    ba.f
    // I don't want next line to compile:
    try { b.f } catch { case e: RuntimeException => println(e) }
  }
}

编辑:解决方案,感谢@Aaron Novstrup

trait Bar extends Base { self =>
  def f(implicit ev: self.type <:< Foo) = {
    //self.asInstanceOf[Foo].g // [1]
    ev(this).g // [2]
  }
}

现在在main中,b.f不编译.尼斯

编辑2:改变行[1]至[2]反映@Aaron Novstrup的回答变化

编辑3:@Aaron Novstrup在没有使用自我反映变化的答案

trait Bar extends Base {
  /* If this is both Foo and Bar,I can do more */
  def f(implicit ev: this.type <:< Foo) = {
    ev(this).g
  }
}

解决方法

是的你可以:

trait A {
   def bar = println("I'm an A!")
}

trait B { 
   def foo(implicit ev: this.type <:< A) = { 
      ev(this).bar
      println("and a B!")
   }
}

如果对象的静态类型(在调用站点)扩展A,编译器将只能提供证据参数.

相关文章

共收录Twitter的14款开源软件,第1页Twitter的Emoji表情 Tw...
Java和Scala中关于==的区别Java:==比较两个变量本身的值,即...
本篇内容主要讲解“Scala怎么使用”,感兴趣的朋友不妨来看看...
这篇文章主要介绍“Scala是一种什么语言”,在日常操作中,相...
这篇文章主要介绍“Scala Trait怎么使用”,在日常操作中,相...
这篇文章主要介绍“Scala类型检查与模式匹配怎么使用”,在日...