Scala макросы. Как создать экземпляр подкласса и динамически смешать черту

Мотивация:

(не тесно связана с этой темой, но излагает вариант использования. Skippable)

я использую Scala.js написать код React. Теперь у меня есть form который содержит кучу inputс, каждый нуждается в onChange callback в его опорах. См. Контролируемый компонент.

case class Input(info:String,value:String,onChange:(e:Event)=>Unit)

Проблема в: info который не имеет ничего общего с 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 для доступа к состоянию. Так же new Input(...), если не сделать TextInputCtrl общественности. Но если вы делаете, вы несете логику React снаружи.

Что ж. Если черта может быть динамически смешана с экземпляром. Я мог бы создать неконтролируемый чистый Input экземпляр где-нибудь еще, и передать его в компонент React. Гораздо более гибкий. Это даже обеспечивает такие рычаги, как:

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,

================================================== знак равно

Обсуждение других способов достижения разъединяющей цели:

Другие подходы: (но, вероятно, не лучшие решения)

Ниже оба теряют способность черт самопознания напрямую обращаться к другим полям. И трудно последовательно или частично переопределить логику управления.

case class PropsContainer(input:Input,control:Control = Control.empty)

или же:

case class Input(info:String,value:String="",onChange: Control = Control.empty)
def addControl(input:Input,control:Control):Input{
  input.copy(onChange = control)
}

0 ответов

Другие вопросы по тегам