单个类的所有方法的函数类型

编程入门 行业动态 更新时间:2024-10-09 10:25:13
本文介绍了单个类的所有方法的函数类型 - 在Scala中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

不知道如何正确地表达这个(因此,如何查看它),但这里有:

我理解应用于对象的方法如何变成一个函数对象。例如:

case class User(name:String,age:Int) val user = User( ,0) user.name _ //()=>字符串

所以,如果我有一个方法 def meth(f: => String),我可以这样做: meth(user.name _)

是否可以定义一个类型,它具有类的方法作为实例 User ? (从这些方法获得的函数对象,更确切地说)

换句话说, f def meth(f:???)是,为了能够做到这一点: meth(user.name _ )和 meth(user.age _)

谢谢!

解决方案

我想要做这样的事情的唯一方法就是使用宏的。我曾经创建了一个执行以下操作的宏(请注意,当前实现中的一些细节已更改,因此为空)。

case class Metadata(实例:AnyRef,name:String){ def value = ??? //(使用反射来调用`instance`上的`name` } 对象元数据扩展((AnyRef,String)=>元数据){ 隐式def anyToMetadata(sym:Any):Metadata = macro MetadataMacro.anyToMetadataImpl } $ b $ private [staticReflection] object MetadataMacro { def anyToMetadataImpl(c :Context)(sym:c.Expr [Any]):c.Expr [Metadata] = { import c.universe._ val metadata = // match树并创建适当的元数据实例 c.Expr(元数据)} }

在代码中,您可以像这样使用它:

case class User :字符串) def test(元数据:元数据){ println(metadata.name + - >+ metadata.value)} val u = User(test) test(u.name)// name - >测试

大约一年前有效的代码可以在这里找到: ee / scala / staticReflection / Metadata.scala 的。详细了解现在的宏。

如果这是您要查找的内容,请让我知道,以便我可以查看是否可以将原件转换为正常版本。

编辑

我设法让旧的工作。要使用它,只需将代码复制到单独的项目中(我使用Eclipse),然后通过 Java Build Path 链接项目。工作版本:

包ee.scala.staticReflection 导入scala.language.experimental.macros import scala.reflect.macros.Context import language.implicitConversions case class元数据(实例:AnyRef,name:String){ //关于为了改进这部分,欢迎 val runtimeUniverse = scala.reflect.runtime.universe val mirror = runtimeUniverse.runtimeMirror(getClass.getClassLoader) val instanceMirror = mirror.reflect(instance) val method = instanceMirror.symbol.selfType.member(runtimeUniverse newTermName name).asMethod val methodMirror = instanceMirror.reflectMethod(method) def value = methodMirror()元数据扩展((AnyRef,String)=>元数据){ implicit def anyToMetadata(sym:Any):Metadata = macro MetadataMacro.anyToMetadataImpl } private [staticReflection] object MetadataMacro { def anyTo MetadataImpl(c:Context)(sym:c.Expr [Any]):c.Expr [Metadata] = { import c.universe._ def createMetadataInstance(select:Select) :Tree = treeBuild.mkMethodCall( c.mirror.staticModule(ee.scala.staticReflection.Metadata), newTermName(apply), List(select .qualifier,Literal(常量(select.name.toString)))) val元数据= sym.tree匹配{ //正常选择 case select:Select => ; createMetadataInstance(select) //可以是使用右关联运算符的调用 case Ident(name)=> c.enclosingMethod.collect { case ValDef(_,refName,_,select:Select)if refName == name => createMetadataInstance(select)} .headOption .getOrElse(抛出新的异常(无法找到ValDef for+ name)) case _ => (无法创建元数据)} c.Expr(元数据)} }

编辑2

全部应用上面的东西的原始海报的问题。您可以像这样使用它。

case class User(name:String,age:Int) val user = User (元数据:元数据)= { println(metadata.name + - >+ metadata.value)} $ b(,0) def meth $ b meth(user.name) meth(user.age)

请注意,解决方案与建议的不同,但在 meth 函数中,您可以执行相同的操作(更均匀一些)。

Not sure how to properly formulate this (hence, how to look it up), but here goes:

I understand how a method applied to an object can become a function object. For example:

case class User(name: String, age: Int) val user = User("", 0) user.name _ // () => String

So, if I had a method def meth(f: () => String), I could do: meth(user.name _)

Is is possible to define a type that has as instances the methods of class User ? (the function objects obtained from these methods, more precisely)

In order words, what would the type of f in def meth(f: ???) be, in order to be able to do this: meth(user.name _) and meth(user.age _)

Thanks!

解决方案

I guess the only way to do something like that is to use macro's. I once created a macro that does the following (note that some details changed in the current implementation and thus are empty).

case class Metadata(instance: AnyRef, name: String) { def value = ??? // use reflection to invoke `name` on `instance` } object Metadata extends ((AnyRef, String) => Metadata) { implicit def anyToMetadata(sym: Any): Metadata = macro MetadataMacro.anyToMetadataImpl } private[staticReflection] object MetadataMacro { def anyToMetadataImpl(c: Context)(sym: c.Expr[Any]): c.Expr[Metadata] = { import c.universe._ val metadata = // match the tree and create the appropriate metadata instance c.Expr(metadata) } }

In code you would then use it like this:

case class User(name:String) def test(metadata:Metadata) { println(metadata.name + "->" + metadata.value) } val u = User("test") test(u.name) // name -> test

The code as it was valid almost a year ago can be found here: ee/scala/staticReflection/Metadata.scala. More info about macros as they are now.

If this is what you were looking for, please let me know so I can see if I can convert the original to a working version.

Edit

I managed to get the old one working. To use it simply copy-past the code into a separate project (I use Eclipse) and then link the projects via the Java Build Path. Working version:

package ee.scala.staticReflection import scala.language.experimental.macros import scala.reflect.macros.Context import language.implicitConversions case class Metadata(instance: AnyRef, name: String) { // any comments on how to improve this part are welcome val runtimeUniverse = scala.reflect.runtime.universe val mirror = runtimeUniverse.runtimeMirror(getClass.getClassLoader) val instanceMirror = mirror.reflect(instance) val method = instanceMirror.symbol.selfType.member(runtimeUniverse newTermName name).asMethod val methodMirror = instanceMirror.reflectMethod(method) def value = methodMirror() } object Metadata extends ((AnyRef, String) => Metadata) { implicit def anyToMetadata(sym: Any): Metadata = macro MetadataMacro.anyToMetadataImpl } private[staticReflection] object MetadataMacro { def anyToMetadataImpl(c: Context)(sym: c.Expr[Any]): c.Expr[Metadata] = { import c.universe._ def createMetadataInstance(select: Select): Tree = treeBuild.mkMethodCall( c.mirror.staticModule("ee.scala.staticReflection.Metadata"), newTermName("apply"), List(select.qualifier, Literal(Constant(select.name.toString)))) val metadata = sym.tree match { //normal select case select: Select => createMetadataInstance(select) //could be a call using a right associative operator case Ident(name) => c.enclosingMethod.collect { case ValDef(_, refName, _, select: Select) if refName == name => createMetadataInstance(select) } .headOption .getOrElse(throw new Exception("Could not find ValDef for " + name)) case _ => throw new Exception("Could not create metadata") } c.Expr(metadata) } }

Edit 2

To apply all of the above stuff to the question of the original poster. You could use it like this

case class User(name: String, age: Int) val user = User("", 0) def meth(metadata: Metadata) = { println(metadata.name + "->" + metadata.value) } meth(user.name) meth(user.age)

Note that the solution is different from what was proposed, but within the meth function you can do the same (a bit more even).

更多推荐

单个类的所有方法的函数类型

本文发布于:2023-11-25 17:58:19,感谢您对本站的认可!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:函数   类型   方法

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!