2016-07-04 65 views
1

我想擴展我的參數化 trait Field[T]與方法返回this.type使用Pimp my Library模式。但我堅持編譯錯誤。我嘗試了一些變體,但沒有成功。可以使用返回this.type的方法對參數化特徵「Pimp my Library」嗎?

我做錯了嗎?或者要求不可能的?

這裏是我的測試例子:

trait Field[T] 

class IntField extends Field[Int] { 
    def getInt = 5 
} 

// Variant 1: return field.type 
object Var1 { 
    implicit class RichField[T](val field: Field[T]) { 
    def bar(fn: T => String): field.type = { 
     // some actions using T 
     field 
    } 
    } 

    new IntField().bar(_.toString).getInt // Error: value getInt is not a member of Field[Int] 
} 

// Variant 2: use two type parameters 
object Var2 { 
    implicit class RichField[T, F <: Field[T]](val field: F) { 
    def bar(fn: T => String): F = { 
     // some actions using T 
     field 
    } 
    } 

    new IntField().bar(_.toString).getInt // <-- Error: value bar is not a member of IntField 
} 

// Variant 3: use higher kinds 
object Var3 { 
    import scala.language.higherKinds 

    implicit class RichField[F[X] <: Field[X], T](val field: F[T]) { 
    def bar(fn: T => String): F[T] = { 
     // some actions using T 
     field 
    } 
    } 

    new IntField().bar(_.toString).getInt // <-- Error: value getInt is not a member of Field[Int] 
} 

更新:參數T是方法bar重要的是,它不能被忽略。

回答

2

在變種2中,您沒有在任何地方使用T。只是將其刪除,編譯器將不再被迷惑:

implicit class RichField[F <: Field[_]](val field: F) { 
    def bar: F = field 
} 

UPDATE:如果您確實需要T,因爲你在留言中提到,一個可能的解決辦法是這樣的:

implicit class RichField[T, F <: Field[_]](val field: F with Field[T]) { 
    def bar(fn: T => String): F = { 
    // some actions using T 
    field 
    } 
} 

這裏有一個證明,它按預期工作(使用toString作爲例子,因爲toString在每個類上都可用,所以即使編譯器推斷Any代碼已經編譯,也不是一個好的測試):

scala> case class Foo(name: String) 
defined class Foo 

scala> class FooField extends Field[Foo] { 
    | def getInt = 5 
    | } 
defined class FooField 

scala> new FooField().bar(_.name).getInt 
res8: Int = 5 
+0

對不準確的過分簡化的例子(我剛纔更新了它)。但是我需要方法'bar'中的'T'。無論如何,感謝您的幫助。 –

+0

哇,好的破解!作品完美無瑕。我非常感謝你的幫助。 –

相關問題