4

scala中trait和abstract class在隐式转换中的区别

 2 years ago
source link: https://my.oschina.net/u/2963604/blog/5074058
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

scala中trait和abstract class在隐式转换中的区别

说半天还不如看一点代码更清楚问题之所在:

object ImplicitObject3 {
def main(args: Array[String]): Unit = {
    def sum[A](xs:List[A])(implicit st:SubTemplate[A]):A = {
      if(xs.isEmpty) st.unit
      else st.add(xs.head,sum(xs.tail))
    }
    
    implicit object SubTemplateImplicitIntValue extends SubTemplate[Int] {
      override def unit: Int = 0

      override def add(x: Int, y: Int): Int = x + y
    }
    implicit object SubTemplateImplicitStringVlaue extends SubTemplate[String] {
      override def unit: String = ""

      override def add(x: String, y: String): String = x + y
    }
    println(sum(List(1,2,3,4,5)))
    println(sum(List("abc","efg","hijk")))
  }
}
trait Template[A] {
  def add(x:A,y:A):A
}
trait SubTemplate[A] extends Template[A] {
  def unit:A
}

编译正确,执行时:在类加载器加载时出现异常。但是将二个trait放在object ImplicitObject3中,不管是放在main的前面还是后面都执行OK:

object ImplicitObject3 {
trait Template[A] {
  def add(x:A,y:A):A
}
trait SubTemplate[A] extends Template[A] {
  def unit:A
}
def main(args: Array[String]): Unit = {
    def sum[A](xs:List[A])(implicit st:SubTemplate[A]):A = {
      if(xs.isEmpty) st.unit
      else st.add(xs.head,sum(xs.tail))
    }
    
    implicit object SubTemplateImplicitIntValue extends SubTemplate[Int] {
      override def unit: Int = 0

      override def add(x: Int, y: Int): Int = x + y
    }
    implicit object SubTemplateImplicitStringVlaue extends SubTemplate[String] {
      override def unit: String = ""

      override def add(x: String, y: String): String = x + y
    }
    println(sum(List(1,2,3,4,5)))
    println(sum(List("abc","efg","hijk")))
  }
}

如果将二个trait改为abstract class形式,定义在object ImplicitObject3之外执行也OK:

object ImplicitObject3 {
def main(args: Array[String]): Unit = {
    def sum[A](xs:List[A])(implicit st:SubTemplate[A]):A = {
      if(xs.isEmpty) st.unit
      else st.add(xs.head,sum(xs.tail))
    }
    
    implicit object SubTemplateImplicitIntValue extends SubTemplate[Int] {
      override def unit: Int = 0

      override def add(x: Int, y: Int): Int = x + y
    }
    implicit object SubTemplateImplicitStringVlaue extends SubTemplate[String] {
      override def unit: String = ""

      override def add(x: String, y: String): String = x + y
    }
    println(sum(List(1,2,3,4,5)))
    println(sum(List("abc","efg","hijk")))
  }
}
abstract class Template[A] {
  def add(x:A,y:A):A
}
abstract class SubTemplate[A] extends Template[A] {
  def unit:A
}

为什么会有这样的现象,原因是什么呢???????????????????????

当我在object ImplicitObject3外面定义二个trait之外,还在二个trait同级定义了一个继承自SubTemplate[A]的abstract class类,同时将main中二个implicit object继承的父改为这个抽象类,则一切都OK了。这种情况下,实验OK,其实原因好理解:

object ImplicitObject3 {
def main(args: Array[String]): Unit = {
    def sum[A](xs:List[A])(implicit st:SubTemplate[A]):A = {
      if(xs.isEmpty) st.unit
      else st.add(xs.head,sum(xs.tail))
    }
    
    implicit object SubTemplateImplicitIntValue extends abstractTemplate[Int] {
      override def unit: Int = 0

      override def add(x: Int, y: Int): Int = x + y
    }
    implicit object SubTemplateImplicitStringVlaue extends abstractTemplate[String] {
      override def unit: String = ""

      override def add(x: String, y: String): String = x + y
    }
    println(sum(List(1,2,3,4,5)))
    println(sum(List("abc","efg","hijk")))
  }
}
trait Template[A] {
  def add(x:A,y:A):A
}
trait SubTemplate[A] extends Template[A] {
  def unit:A
}
abstract class abstractTemplate[A] extends SubTemplate[A]

有一次无意中,我将二个trait放在另一个单独的scala文件中,然后我编译工程然后调试,不成功。鬼使神差地在main的最开头import SubTemplate一次,居然成功了。我将磁盘上所有class文件都删除了再编译工程却又不成功。然后再去掉import,单独编译那个scala文件,再编译工程却又成功执行代码了。总结来看:这是由于IDEA造成class文件与源代码不一致的原因


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK