2013-08-18 33 views
2

我對Scala編程頗爲陌生,所以仍然想出了執行某些操作的規範方法。最近,我想編寫一個函數foo,它只接受一組參數的類型。想想類似在Scala中模擬函數過載

def foo(x: [Int, String]) = ??? 

但我找不到任何接近上面的語法(這是我覺得最自然的我)。使用Any類型會使編譯端檢查失去作用,並且會使問題更容易轉移到運行時的土地上。

我能想出的最好的是這樣的:

sealed abstract class Base 
case class TypeInt(v: Int) extends Base 
case class TypeString(v: String) extends Base 

implicit def toTypeInt(v: Int) = TypeInt(v) 
implicit def toTypeString(v: String) = TypeString(v) 

def foo(x: Base) = x match { 
    case TypeInt(v) => println("Int: ", v) 
    case TypeString(v) => println("String: ", v) 
} 

foo(1) 
foo("hello") 

(作爲一個方面說明,我希望能夠只寫implicit case class ...避免手動創建toType*功能,但不編譯。)

是否有一種更簡單的方法來編寫一個接受類型安全方式的一組類型參數的函數?

UPDATE:它實際上證明,在我的具體情況下,我可以只使用方法重載。由於某些原因,在Scala工作表中根本無法使用方法重載,這讓我認爲Scala根本沒有超載。但我錯了 - 在普通的Scala源中應該可以使用它。在下面的註釋中提到的關於磁鐵模式的文章中描述了重載使用的一些缺點(例如,由於JVM泛型中的類型擦除,無法重載類型Foo [Type1]和Foo [Type2]。

+3

您正試圖重新發明[磁鐵模式](http://spray.io/blog/2012-12-13-the-magnet-pattern/) –

+0

謝謝 - 我會讀取該鏈接。 –

+1

@AlexeyAlexandrov:你應該將你的「更新」移到答案上,並接受它來標記你的問題爲答案。 – senia

回答

4

磁鐵模式感覺就像矯枉過正這裏,你可以使用普通的舊型類:

trait Fooable[A] { def apply(a: A): Unit } 

implicit object intFooable extends Fooable[Int] { 
    def apply(a: Int) = printf("Int: %d\n", a) 
} 

implicit object stringFooable extends Fooable[String] { 
    def apply(a: String) = printf("String: %s\n", a) 
} 

def foo[A: Fooable](a: A) = implicitly[Fooable[A]].apply(a) 

然後:

scala> foo(1) 
Int: 1 

scala> foo("hello") 
String: hello 

假如你擔心刪除之後的衝突讓我們嘗試一些泛型類型的實例:

trait Bar[A] 

implicit object barIntFooable extends Fooable[Bar[Int]] { 
    def apply(a: Bar[Int]) = println("A bar of ints.") 
} 

implicit object barStringFooable extends Fooable[Bar[String]] { 
    def apply(a: Bar[String]) = println("A bar of strings.") 
} 

並再次:按預期工作

scala> foo(new Bar[Int] {}) 
A bar of ints. 

scala> foo(new Bar[String] {}) 
A bar of strings. 

一切。