scala泛型疑问,为什么下面这段代码无法编译

112 views
Skip to first unread message

Fei Wang

unread,
Apr 19, 2014, 6:12:34 AM4/19/14
to sca...@googlegroups.com
trait Computer[A] {
    def compute(x:A, y:A):A
}

class Adder[A] extends Computer[A] {
    def compute(x:A, y:A): A = {
        x + y // 无法编译,提示类型不正确
    }
}

这里为什么会出现类型不正确呢?需要对x和y做类型限定吗,他们必须能做加运算?应该怎么改呢

Liu Sam

unread,
Apr 23, 2014, 9:21:24 PM4/23/14
to sca...@googlegroups.com
似乎是说这样写太泛了,呵呵……谁能保证 A 这个 Any 类型的对象一定有“+”这个方法呢?
这个问题的准确需求是什么呢?

Best regards!

Sam Liu



--
您收到此邮件是因为您订阅了Google网上论坛中的“Scala中文社区”论坛。
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到scalacn+u...@googlegroups.com
要发帖到此论坛,请发送电子邮件至sca...@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout

Liu Sam

unread,
Apr 23, 2014, 9:28:40 PM4/23/14
to sca...@googlegroups.com
如果需求是传入不同类型的对象,执行不同的加法,则可以具体实现如下:

trait Computer[A] {
    def compute(x:A, y:A):A
}

class Adder[A] extends Computer[A] {
  def compute(x:Int, y:Int):Int = {
    x + y
  }
  def compute(x:String, y:String):String = {
    x + y
  }
}

Best regards!

Sam Liu



Liu Sam

unread,
Apr 23, 2014, 9:31:58 PM4/23/14
to sca...@googlegroups.com
还有报错,不好意思,试试这样:

object Hello extends App {

  println("Hello World!")
  val adder:Adder[Int]  = new Adder[Int]
  println(adder.compute(9, 3))
  val addstr:Adder[String]  = new Adder[String]
  println(addstr.compute("fd", "df"))
}

trait Computer[A] {
    def compute(x:A, y:A):A = {
      x
    }
}

class Adder[A] extends Computer[A] {
  def compute(x:Int, y:Int):Int = {
    x + y
  }
  def compute(x:String, y:String):String = {
    x + y
  }
}

Best regards!

Sam Liu



Xiang Zhang

unread,
Apr 23, 2014, 11:10:34 PM4/23/14
to sca...@googlegroups.com
我不太了解scala,但是在F#中,这种情况需要用到inline, 泛型的类型和C++中模板类型参数是不同的,泛型中的类型是runtime类型,编译期无法决定,所以你必须对泛型类型有所约束,比如添加constraints,要求有某些静态方法。

Caoyuan

unread,
Apr 24, 2014, 4:04:46 AM4/24/14
to sca...@googlegroups.com
你这样当然编译不过,就像Liu Sam说的,A没有任何它具有+这个接口的信息。

方案1:
trait Plusable {
  def +(x: Plusable): Plusable
}

trait Computer[A <: Plusable] {
    def compute(x:A, y:A):A
}

class Adder[A <: Plusable] extends Computer[A] {
    def compute(x:A, y:A): A = {
        x + y // 无法编译,提示类型不正确
    }
}

方案2,使用Structural Type

type  Plusable = {
  def +(x: Any): Any
}

trait Computer[A <: Plusable] {
    def compute(x:A, y:A):A
}

class Adder[A <: Plusable] extends Computer[A] {
    def compute(x:A, y:A): A = {
        x + y // 无法编译,提示类型不正确
    }
}


方案1中所有的A必须实现Plusable,这是一种静态强约束。
方案2中所有的A只要有def +(x: Any): Any方法即可,不必扩展成Plusable(Plusable只是一个别名),但运行时在JVM中是采用反射实现的,运行性能会受影响。

杨博

unread,
Apr 28, 2014, 1:58:02 AM4/28/14
to sca...@googlegroups.com
草原哥的写法不错。我再补充个更符合Scala惯例的非侵入做法,不需要修改A的实现,而只要给A添加能隐式找到的助手类就可以了:

def compute[A](x:A, y:A)(implicit numeric: Numeric[A]):A = {
  import numeric._
  x + y
}
assert(compute(1, 2) == 3)
assert(compute(1.2, 3.4) == 4.6)

那个Computer基类看着扎眼,我给删了。

在 2014年4月24日星期四UTC+8下午4时04分46秒,Caoyuan写道:
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到scalacn+unsubscribe@googlegroups.com

要发帖到此论坛,请发送电子邮件至sca...@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
您收到此邮件是因为您订阅了Google网上论坛中的“Scala中文社区”论坛。
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到scalacn+unsubscribe@googlegroups.com

要发帖到此论坛,请发送电子邮件至sca...@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout

--
您收到此邮件是因为您订阅了Google网上论坛中的“Scala中文社区”论坛。
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到scalacn+unsubscribe@googlegroups.com

Nicholas Ren

unread,
Apr 28, 2014, 2:39:45 AM4/28/14
to sca...@googlegroups.com
草原老师的方案1,在我这儿还是编译不通过:

class Adder[A <: Plusable] extends Computer[A] {
  def compute(x: A, y: A): A = x + y  //此行出错
}

type mismatch;
 found   : A$A3.this.Plusable
 required: A
  def compute(x: A, y: A): A = x + y
                                 ^

方案2,也编译失败:
error: type mismatch;
 found   : Any
 required: A
  def compute(x:A, y:A): A = x + y
                               ^

对于第一种方案, 我的理解是,定义一个支持`+`操作的Plusable trait,把Adder的类型参数A的上界设置为Plustable,通过类型上界限定A能够支持`+`操作,然而却编译失败,不理解。

对于第二种方案,Structural Type不了解。

杨博的方案通过隐式转换解决了`+`操作找不到的问题,很漂亮。但是我仍然很想知道草原老师的方案一为啥在我这儿编译失败。

-- 
Nicholas Ren (任晓君)

ThoughtWorks | Xi'an | GMT+8

要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到scalacn+u...@googlegroups.com

杨博

unread,
Apr 28, 2014, 3:05:25 AM4/28/14
to sca...@googlegroups.com
在 2014年4月28日 下午2:39,Nicholas Ren <nichol...@gmail.com>写道:
草原老师的方案1,在我这儿还是编译不通过:

class Adder[A <: Plusable] extends Computer[A] {
  def compute(x: A, y: A): A = x + y  //此行出错
必须改成def compute(x: A, y: A): A = (x + y).asInstanceOf[A] 


--
您收到此邮件是因为您订阅了Google网上论坛“Scala中文社区”中的主题。
要退订此主题,请访问https://groups.google.com/d/topic/scalacn/wAyj7aYtocg/unsubscribe
要退订此论坛及其所有主题,请发送电子邮件到scalacn+u...@googlegroups.com

要发帖到此论坛,请发送电子邮件至sca...@googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
杨博 (Yang Bo)

Caoyuan

unread,
Apr 28, 2014, 4:56:08 AM4/28/14
to sca...@googlegroups.com
杨博的改法能编译就好。我只是随手写了一下代码说思路,没有真正去测过的 :-)

Nicholas Ren

unread,
Apr 28, 2014, 6:02:08 AM4/28/14
to sca...@googlegroups.com
发一个最终work的版本:

 

-- 
Nicholas Ren (任晓君)

ThoughtWorks | Xi'an | GMT+8

Screen Shot 2014-04-28 at 6.01.33 PM.png
Reply all
Reply to author
Forward
0 new messages