2013-05-08 23 views
7

Tôi đã triển khai mã được đề cập trong Get companion object instance with new Scala reflection API (mã từ đây https://gist.github.com/xeno-by/4985929).Lấy thể hiện đối tượng đồng hành của một modul bên trong với API phản chiếu Scala

Điều này phù hợp với mọi lớp tiêu chuẩn của các kiểu chữ thường. Đáng tiếc là trong một số lớp học của dự án tôi nhận được một ngoại lệ: scala.ScalaReflectionException: object Tensor is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror Trường hợp ngoại lệ là khá rõ ràng, vì vậy tôi đã cố gắng để thay đổi mã của tôi như sau:

object Reflection { 
    def getCompanionObject(caseclassinstance:Product):Any = { 
     import scala.reflect.runtime.{currentMirror => cm} 
     val classSymbol = cm.classSymbol(caseclassinstance.getClass) 
     val moduleSymbol = classSymbol.companionSymbol.asModule 
     val instanceMirror = cm.reflect(caseclassinstance) 
     val moduleMirror = instanceMirror.reflectModule(moduleSymbol) 
     moduleMirror.instance 
    } 
} 

Nhưng bây giờ tôi nhận được một scala.ScalaReflectionException: expected a member of class Tensor, you provided object Prototype2.SPL.SPL_Exp.Tensor và tôi đã không tìm hiểu làm thế nào để thay đổi mã để sửa lỗi này. Bất kỳ trợ giúp nào cũng được đánh giá rất cao!

Cập nhật: Tôi cung cấp một số mã cho lặp lại tốt hơn:

scala> trait SPL { 
    | case class Tensor() 
    | } 
defined trait SPL 

scala> val s = new SPL {} 
s: SPL = [email protected] 

scala> val t = s.Tensor() 
t: s.Tensor = Tensor() 

scala> object Reflection { /* as in the first code snippet*/} 
defined module Reflection 

scala> Reflection.getCompanionObject(t) 
scala.ScalaReflectionException: object Tensor is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror 
... 

scala> object Reflection { /* as in the second code snippet*/} 
defined module Reflection 

scala> Reflection.getCompanionObject(t) 
scala.ScalaReflectionException: expected a member of class Tensor, you provided object SPL.Tensor 
... 
+0

Câu hỏi này có thể liên quan http://stackoverflow.com/questions/11084408/scala-reflection-error-this-is-an-inner-module-use-reflectmodule-on-an-instanc – leo

Trả lời

3

Bạn nên có một thể hiện của mô-đun. Bạn có thể lấy gương cho biểu tượng Tensor chỉ từ gương của Spl.

trait Spl { 
    case class Tensor(s: String) 
} 

val spl = new Spl {} 

val t = spl.Tensor("T") 

// mirror for module spl 
val moduleMirror = cm.reflect(spl) 
// class symbol for Tensor 
val instanceSymbol = cm.classSymbol(t.getClass) 
// symbol for companion object 
val companionSymbol = instanceSymbol.companionSymbol.asModule 
// mirror for companion object symbol in spl module mirror 
val companionMirror = moduleMirror.reflectModule(companionSymbol) 

scala> companionMirror.instance 
res0: Any = Tensor 

Bạn có thể nhận được một thể hiện của Spl sử dụng một chút ma thuật xấu xí:

val outer = 
    t. 
    getClass. 
    getFields. 
    find(_.getName == """$outer"""). 
    get. 
    get(t) 

Bạn không nên làm như vậy cho đến khi bạn có thể.

def getCompanionObject(t: Product):Any = { 
    import scala.reflect.runtime.{currentMirror => cm} 
    val outerField = t.getClass.getFields.find(_.getName == """$outer""") 
    val moduleMirror = outerField.map{ _.get(t) }.map{ cm.reflect(_) } 
    val instanceSymbol = cm.classSymbol(t.getClass) 
    val companionSymbol = instanceSymbol.companionSymbol.asModule 
    val companionMirror = 
    moduleMirror. 
     map{ _.reflectModule(companionSymbol) }. 
     getOrElse{ cm.reflectModule(companionSymbol) } 
    companionMirror.instance 
} 
+0

Cảm ơn rất nhiều! Thật không may tôi có (trong trường hợp chung) tham chiếu đến SPL không phải ở bàn tay. Tương ứng các tham số caseclassinstance (có thể không phải là một lớp bên trong của SPL) cần phải là đủ trong trường hợp của tôi để có được đối tượng đồng hành. – leo

+0

Bạn không thể đạt được nó mà không có gương ví dụ của 'SPL'. – senia

+0

@leo: Tôi đã cập nhật câu trả lời của mình. – senia

Các vấn đề liên quan