Dựa trên những gì soc viết, tôi nhận điều này:
import scala.reflect.runtime.universe._
val members = typeOf[MyClass].members.filter(_.typeSignature match {
case tpe if tpe <:< typeOf[ThirdParty] => true
case NullaryMethodType(tpe) if tpe <:< typeOf[ThirdParty] => true
case MethodType(Nil, tpe) if tpe <:< typeOf[ThirdParty] => true
case _ => false
})
Hãy để tôi giải thích các mô hình phù hợp. Loại val
hoặc object
có thể được so sánh trực tiếp, nhưng chức năng có loại hơi khác. Ở đây tôi đang đối chiếu với các phương thức không có danh sách tham số và các phương thức có danh sách tham số zero-arity.
Có một số khác biệt ở đây so với câu trả lời của soc. Trước tiên, tôi sử dụng members
thay vì declarations
. Điều đó trả về các thành viên được kế thừa cũng như các thành viên được khai báo trên chính mình là MyClass
.
Thứ hai, tôi kiểm tra xem đó có phải là thành viên giá trị không, thay vì thành viên loại. Bạn chỉ có thể gọi các phương thức trên các giá trị, vì vậy nó có vẻ là một hạn chế hợp lý, mặc dù có thể không cần thiết. cập nhật. Phương thức isValue
không còn có sẵn trong 2.10.0-RC1, vì vậy tôi đã xóa séc.
Cuối cùng, tôi sử dụng <:<
thay vì kiểm tra từng phụ huynh để bình đẳng.
Bây giờ, đến lời gọi. Tôi sẽ thay đổi mã trên kể từ khi yêu cầu phụ thuộc vào loại thành viên bạn có, vì vậy chúng tôi tốt nhất nên lọc và gọi cùng một lúc. Tôi cũng sẽ thay đổi từ số members
thành nonPrivateMembers
, giả sử đó là điều mong muốn. cập nhật. nonPrivateMembers
không còn có sẵn trong 2.10.0-RC1, sử dụng filter(!_.isPrivate)
nếu cần.
Và tôi cũng sẽ tránh sử dụng typeOf
, sẽ không hoạt động với các gương trên REPL. cập nhật. Trong 2,10.0-RC1 typeOf
đang hoạt động tốt, nhưng tôi sẽ giữ cho bộ xương của việc triển khai không thay đổi.
Tất cả những điều trên cơ bản liên quan đến cấu trúc của sự vật: các thành viên thuộc loại nào, loại thành viên nào, v.v. Khi bạn muốn hãy sử dụng công cụ này, bạn cần gương.
Bất cứ khi nào bạn có biểu tượng hoặc loại cho thứ gì đó - một lớp học, phương pháp, obj, v.v. - bạn hành động trên điều đó thông qua một gương . Để hành động (phản ánh) trên một thể hiện của một đối tượng, bạn cần một cá thể gương. Để hành động trên một phương pháp, bạn cần một phương pháp nhân bản, và như vậy.
Vì vậy, hãy cố gắng xây dựng một functon để làm những gì được yêu cầu:
import scala.reflect.runtime.universe._
def invoke[Target : TypeTag](obj: Any): Seq[Target] = {
val mirror = runtimeMirror(obj.getClass.getClassLoader)
val insMirror = mirror reflect obj
val originType = insMirror.symbol.typeSignature
val targetType = typeTag[Target].tpe
val members = originType.members
val result = members collect (member => member.typeSignature match {
case tpe if tpe <:< typeOf[ThirdParty] =>
if (member.isModule)
(insMirror reflectModule member.asModule).instance
else
(insMirror reflectField member.asTerm).get
case NullaryMethodType(tpe) if tpe <:< typeOf[ThirdParty] =>
(insMirror reflectMethod member.asMethod).apply()
case MethodType(Nil, tpe) if tpe <:< typeOf[ThirdParty] =>
(insMirror reflectMethod member.asMethod).apply()
})
result.map(_.asInstanceOf[Target]).toSeq
}
Lưu ý rằng lồng module không thể được phục hồi với Scala 2.10.0-M4 - mà ta có thể với M5 hoặc RC1. Để kiểm tra mã này bằng M4, hãy thay thế mã mô-đun bằng null
.
Dưới đây là một ví dụ:
scala> class MyClass {
object objA extends ThirdParty
object objB extends WeatherIcon
val aVal = new ThirdParty {}
val bVal = new WeatherIcon {}
def aDef = new ThirdParty {}
def bDef = new WeatherIcon {}
def anotherDef() = new ThirdParty {}
def yetAnotherDef() = new WeatherIcon {}
}
defined class MyClass
scala> invoke[ThirdParty](new MyClass)
res88: Seq[ThirdParty] = List([email protected], [email protected], [email protected], null)
Phần lớn đẹp hơn ví dụ của tôi! Cảm ơn! – soc
Tôi nghĩ typeSignature trả về NullaryMethodTypes, không phải là các kiểu con của ThirdParty? Bạn có thể in '_.typeSignature.kind' không? –
Phần yêu cầu có thể được thực hiện bằng API gương. Thông tin thêm tại đây: http://stackoverflow.com/questions/11020746/get-companion-object-instance-with-new-scala-reflection-api/11031443#11031443. Trong ngắn hạn, bạn sẽ cần phải thực hiện 'runtimeMirror (getClass.getClassLoader) .reflect (). ReflectMethod () ()' –