Scala宏。如何实例化子类并动态混合特征

时间:2017-03-02 02:36:53

标签: scala macros traits scala-quasiquotes scalajs-react

动机:

(与此主题没有紧密关联但声明用例。可跳过)

我正在使用addRowHandlers()来编写React代码。我现在有一个... reader.onload = function() { // (create table rows...) addRowHandlers(); // now there are rows to select :) } ,其中包含一堆Scala.js个,每个都需要一个form的道具。请参阅Controlled component

input

问题是:onChange callbackcase class Input(info:String,value:String,onChange:(e:Event)=>Unit) 无关,但与之相关。我会将控制逻辑与Web内容分开。所以我做了:

info

这只解决了耦合问题的一半。因为React的实现必须在React组件内部写入访问状态。 trait Control[T]{val value:T,val onChange:(e:Event)=>Unit} case class Input(info:String) //when need to create a controlled props: private trait TextInputCtrl extends Control[String]{//..implementation} new Input("some info") with TextInputCtrl 也一样,除非公开TextInputCtrl。但如果你这样做,你可以在外面运行React逻辑。

好。 如果可以将trait动态混合到实例中。我可以在其他地方创建一个不受控制的干净new Input(...)实例,并将其传递给React组件。更加灵活。这甚至提供了杠杆作用:

TextInputCtrl

所以,我做了一些尝试:

问题:

我想用这个简单的哲学:

Input

但是通过宏:

Seq(input...).map(_ with XXControl)

我成功编译了。但在运行时失败了:

def dynamix(in:Input):Input with Control{
  new Input(in.info) with Control{//..implementation}
}

它抛出:

 q"""
   new $MixinToolSym[$tpeC,$tpeT]{
       def dynamix(in: $tpeC): $tpeC with $tpeT = {
          new $tpeC (..$constrBody) with $tpeT
       }
   }
 """

有什么问题?

这不是trait MixinTool[C, T] { def dynamix(in: C): C with T } object MixinTool { implicit def materialize[C, T]: MixinTool[C, T] = macro MacroImpl.impl[C, T] } val mt=MixinTool.materialize[Input,Control] mt.dynamix(inputInstance) //error 的问题。

=============================================== ====

讨论达到脱钩目标的其他方法:

其他方法: (但可能不是最佳解决方案

以下两者都失去了自我类型特征直接访问其他领域的能力。并且难以逐步链接或部分覆盖控制逻辑。

java.lang.IllegalAccessError: 
tried to access field x.x.Input.info from class x.x.X$$anon$3$$anon$2

或:

scala App

0 个答案:

没有答案