2015-05-08 36 views
1

給定一個具體類特定性狀匿名子束縛

trait Trt { 
    val x: Int 
} 

class C extends Trt { 
    val x: Int = 3 
} 

我想,以創建一個匿名類的參數類型的對象覆蓋屬性x

abstract class SomeClass[T <: Trt : ClassTag] { 
    def f: Unit = { 
     val original = new C 

     //Is this even possible? 
     val withOverridenX = new T { override val x = 42} 

     assert(original.x != withOverridenX.x) 
    } 
} 

的問題是,編譯器不斷報告以下錯誤:

>> Error:(26, 35) class type required but T found 

實例化匿名類擴展參數類型類甚至可能嗎?

我知道問題是,T是一個類型,而不是一個類,我想知道是否也許,由於ClassTag界限的情況下,它可以實例化withOverridenX

+0

的[可能重複爲什麼\'性狀t; C類; class X extends(C with T)''不能被編譯?](http://stackoverflow.com/questions/25960083/why-trait-t-class-c-class-x-extends-c-with- t-can-be-compiled) – sjrd

+0

@sjrd是否有任何方法可以(例如使用ClassTag)實例化參數類型的匿名類(是的,我知道它是一種類型),在運行時提供類信息,不知何故,使用它? –

+0

不,沒有辦法做到這一點,即使使用「ClassTag」。你會需要一個'TypeTag'和編譯時反射(宏)來做到這一點,我想(我不完全知道如何)。 – sjrd

回答

1

你不能實例化T,因爲它在運行時並不知道,只是在編譯時。 ClassTag只會通過runtimeClass方法讓您訪問Class對象T。但是就此而言,您不能通過調用new繼承T,因爲例如沒有證據表明T具有無參數構造函數。

+0

是的,但這就是爲什麼我試圖使用由上下文綁定給出的「ClassTag」的證據。 –

+0

我詳細闡述了一點mor,參見上文。 – Chirlo

+0

我找到了一個解決方法,請檢查我的autoanswer –

0

我找到了一個解決方法,它允許做的正是我想要的是:與x比在其聲明時給出了一個不同的值獲取的C實例(或C一個子類)。

每當有人想要濫用編程語言時,通常會轉向反思。自2.10版本,Scala提供its own reflection能力(除了Java的),所以它是可以改變xwithOverridenX

import scala.reflect.runtime.universe._ 

abstract class SomeClass[T <: Trt : TypeTag ] { 
    def f: Unit = { 
     val original = new C 
     val withOverridenX = new C 

     //This gets the term representation for the attribute 'x'... 
     val xTerm = typeOf[T].declaration(newTermName("x")).asTerm 

     //... which can be used to reflect the attribute: 
     val m = runtimeMirror(getClass.getClassLoader) 
     val reflectedC = m.reflect(withOverridenX) 
     val reflectedX = reflectedC.reflectField(xTerm) 

     reflectedX.set(42) 

     assert(original.x != withOverridenX.x) 
    } 
}