2012-04-26 107 views
1

不時,我處理有東西像它下面的Java:自然斯卡拉 - 約束泛型類型特定類型

def printDbl(d:Double) { println("dbl: " + d) } 
def printInt(i:Int) { println("int: " + i) } 

,我想在一些斯卡拉包裹這一點,這最終看起來像這樣:

def print[T:Manifest] (t:T) { 
    if (manifest[T] <:< manifest[Int]) { printInt(t.asInstanceOf[Int]) ; return } 
    if (manifest[T] <:< manifest[Double]) { printDbl(t.asInstanceOf[Double]) ; return } 

    throw new UnsupportedOperationException("not implemented: " + manifest[T]) 
} 

,但是當我運行下面,我得到一個運行時異常:

print(1) 
print(2.0) 
print("hello") 

我似乎還記得有一種方法可以在編譯時捕捉到這一點,但我似乎無法將其調出。也許一些巧妙的隱含轉換?

回答

0
def printDbl(d:Double) { println("dbl: " + d) } 
def printInt(i:Int) { println("int: " + i) } 

trait Printer[T] { def print(t:T) } 
class PD extends Printer[Double] { def print(d:Double) = printDbl(d) } 
class PI extends Printer[Int] { def print(i:Int) = printInt(i) } 
implicit val pd = new PD() 
implicit val pi = new PI() 

def print[T](t:T)(implicit printer:Printer[T]) = printer.print(t) 

print(1) // 1 
print(2.0) // 2.0 
print("hello") // Error:(88, 7) could not find implicit value for parameter printer: A$A336.this.Printer[String] 
6

你爲什麼不只是採取的方法重載的優勢,寫你的斯卡拉包裝這樣?:

object Printer { 
    def print(d: Double) { printDbl(d) } 
    def print(i: Int) { printInt(i) } 
} 

這是非常簡單的,並提供所需的行爲:

import Printer._ 
print(1.)   // dbl: 1.0 
print(1)   // int: 1 
print("hello")  // compile-time type error 
1
scala> object SpecType { 
    | trait SpecType[T] { 
    |  def is(s: String): Boolean 
    | } 
    | implicit object DoubleType extends SpecType[Double] { 
    |  def is(s: String) = s == "Double" 
    | } 
    | implicit object IntType extends SpecType[Int] { 
    |  def is(s: String) = s == "Int" 
    | } 
    | } 
defined module SpecType 


scala> import SpecType._ 
import SpecType._ 

scala> def print[T: SpecType](x: T) { 
    | if(implicitly[SpecType[T]].is("Int")) println("Int") 
    | if(implicitly[SpecType[T]].is("Double")) println("Double") 
    | } 
print: [T](x: T)(implicit evidence$1: SpecType.SpecType[T])Unit 

scala> print(1) 
Int 

scala> print(1.0) 
Double 

scala> print("") 
<console>:21: error: could not find implicit value for evidence parameter of typ 
e SpecType.SpecType[String] 
       print("") 
+3

此代碼不好。 – 2012-04-26 08:54:03

+1

我想這個代碼可以通過使用Double/Int而不是String來改進,並且改變代碼的佈局,這樣你就可以做一些事情:隱式地[SpecType [T]]。println(x)例如:http:/ /debasishg.blogspot.de/2010/06/scala-implicits-type-classes-here-i.html – Christian 2012-04-26 09:34:40

0

這是最好的我想出

class CanPrint[T] (t:T) { def getT = t} 
implicit def canPrint(i:Int) = new CanPrint[Int](i) 
implicit def canPrint(d:Double) = new CanPrint[Double](d)  

def print[T:Manifest] (t:CanPrint[T]) { 
    if (manifest[T] <:< manifest[Int]) { printInt(t.getT.asInstanceOf[Int]) ; return } 
    if (manifest[T] <:< manifest[Double]) { printDbl(t.getT.asInstanceOf[Double]) ; return } 

    throw new UnsupportedOperationException("not implemented: " + manifest[T]) 
} 

以下不編譯

print(1) 
print(1.0) 
print("hello") 

和下面做什麼,我希望

print(1) 
print(1.0) 

然而,這是不好的代碼,因爲我不得不進口隱含DEFS爲它工作,並作爲這個代碼的消費者,我看到的是方法簽名,說我必須傳遞一個CanPrint對象,我可以實例化。

print(new CanPrint("hello")) // pwned 

我可以使構造函數是私有的,只能訪問隱式方法或一些這樣的?