Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 强制执行案例对象的名称_Scala_Functional Programming - Fatal编程技术网

Scala 强制执行案例对象的名称

Scala 强制执行案例对象的名称,scala,functional-programming,Scala,Functional Programming,鉴于此代码: sealed trait Parent case object GetOne extends Parent case object GetTwo extends Parent 在Scala中是否可以强制执行这些约束: 父对象只能按大小写对象扩展 父对象的子事例对象的名称必须以Get开头。 可能吗 父对象只能按大小写对象扩展 你可能会接近使用。 如@MateuszKubuszok所述 以下是一个例子: sealed trait Foo extends Product with S

鉴于此代码:

sealed trait Parent

case object GetOne extends Parent
case object GetTwo extends Parent
在Scala中是否可以强制执行这些约束:

父对象只能按大小写对象扩展 父对象的子事例对象的名称必须以Get开头。 可能吗

父对象只能按大小写对象扩展

你可能会接近使用。 如@MateuszKubuszok所述

以下是一个例子:

sealed trait Foo extends Product with Serializable { self: Singleton => }
那么这就行了:

final case object A extends Foo
final case object B extends Foo
但这并不是:

final case object A extends Foo
final case class B(blah: String) extends Foo
父对象的子事例对象的名称必须以Get开头

不使用标准Scala。 也许是宏或类似的东西,但真的感觉像是一个奇怪的必要条件;您是否计划通过反射获得这些实例?或者是什么原因想要这样

在任何情况下,代码审查和scalafix规则似乎可以更好地处理这一问题

父对象只能按大小写对象扩展

在Scala 3中,您可以定义


强制成员成为有效的大小写对象。

尝试使用无形状宏

import shapeless.ops.{coproduct, hlist}
import shapeless.{Coproduct, HList, LabelledGeneric}
import shapeless.ops.union.{Keys, Values}

def check[A] = new PartiallyApplied[A]

class PartiallyApplied[A] {
  def apply[C <: Coproduct, K <: HList, V <: Coproduct]()(implicit
    labelledGeneric: LabelledGeneric.Aux[A, C],
    keys: Keys.Aux[C, K],
    values: Values.Aux[C, V],
    allKeysStartWithGet: hlist.LiftAll[StartsWithGet, K],
    allValuesAreObjects: coproduct.LiftAll[IsObject, V]
  ) = null
}

import shapeless.Witness
import scala.language.experimental.macros
import scala.reflect.macros.whitebox

trait StartsWithGet[S]

object StartsWithGet {
  implicit def mkStartsWithGet[S <: Symbol]: StartsWithGet[S] = macro impl[S]

  def impl[S <: Symbol : c.WeakTypeTag](c: whitebox.Context): c.Tree = {
    import c.universe._
    val typ = weakTypeOf[S]
    val witness = c.inferImplicitValue(
      c.typecheck(tq"_root_.shapeless.Witness.Aux[$typ]", mode = c.TYPEmode).tpe,
      silent = false
    )
    val str = c.eval(c.Expr[Witness.Lt[scala.Symbol]](
      c.untypecheck(witness.duplicate)
    )).value.name

    if (str.startsWith("Get"))
      q"new StartsWithGet[$typ] {}"
    else c.abort(c.enclosingPosition, s"$str doesn't start with Get")
  }
}

trait IsObject[A]

object IsObject {
  implicit def mkIsObject[A]: IsObject[A] = macro impl[A]

  def impl[A: c.WeakTypeTag](c: whitebox.Context): c.Tree = {
    import c.universe._
    val typ = weakTypeOf[A]
    if (typ.typeSymbol.isModuleClass)
      q"new IsObject[$typ] {}"
    else c.abort(c.enclosingPosition, s"$typ is not object")
  }
}

sealed trait Parent 
case object GetOne extends Parent
case object GetTwo extends Parent
check[Parent]() // compiles

sealed trait Parent
case object GetOne extends Parent
case object Two extends Parent
check[Parent]() // doesn't compile

sealed trait Parent
case object GetOne extends Parent
case class GetTwo() extends Parent
check[Parent]() // doesn't compile

1.好吧,您最多可以要求父级按产品进行扩展,并使用Singleton进行序列化。2.我想,您可以让parent接受一些隐式参数,这些参数将根据子对象的名称进行解析,并使此隐式参数仅适用于以get开头的名称,使用一些宏。。。基本上类似于密封的抽象类父类[T:StartWithGet]{this:T with Product with Serializable with Singleton},其中StartWithGet[T]仅由宏为名称以get开头的类提供。但这太糟糕了。或者,我的答案中的StartsWithGet可以通过导入shapeless.tag来定义。@@import singleton.ops.{Require,StartsWithGet}trait StartsWithGet[S]对象StartsWithGet{implicit def mkStartsWithGet[S我在Scala 2.11,2.12中,谢谢!这很有帮助
import shapeless.ops.{coproduct, hlist}
import shapeless.{Coproduct, HList, LabelledGeneric}
import shapeless.ops.union.{Keys, Values}

def check[A] = new PartiallyApplied[A]

class PartiallyApplied[A] {
  def apply[C <: Coproduct, K <: HList, V <: Coproduct]()(implicit
    labelledGeneric: LabelledGeneric.Aux[A, C],
    keys: Keys.Aux[C, K],
    values: Values.Aux[C, V],
    allKeysStartWithGet: hlist.LiftAll[StartsWithGet, K],
    allValuesAreObjects: coproduct.LiftAll[IsObject, V]
  ) = null
}

import shapeless.Witness
import scala.language.experimental.macros
import scala.reflect.macros.whitebox

trait StartsWithGet[S]

object StartsWithGet {
  implicit def mkStartsWithGet[S <: Symbol]: StartsWithGet[S] = macro impl[S]

  def impl[S <: Symbol : c.WeakTypeTag](c: whitebox.Context): c.Tree = {
    import c.universe._
    val typ = weakTypeOf[S]
    val witness = c.inferImplicitValue(
      c.typecheck(tq"_root_.shapeless.Witness.Aux[$typ]", mode = c.TYPEmode).tpe,
      silent = false
    )
    val str = c.eval(c.Expr[Witness.Lt[scala.Symbol]](
      c.untypecheck(witness.duplicate)
    )).value.name

    if (str.startsWith("Get"))
      q"new StartsWithGet[$typ] {}"
    else c.abort(c.enclosingPosition, s"$str doesn't start with Get")
  }
}

trait IsObject[A]

object IsObject {
  implicit def mkIsObject[A]: IsObject[A] = macro impl[A]

  def impl[A: c.WeakTypeTag](c: whitebox.Context): c.Tree = {
    import c.universe._
    val typ = weakTypeOf[A]
    if (typ.typeSymbol.isModuleClass)
      q"new IsObject[$typ] {}"
    else c.abort(c.enclosingPosition, s"$typ is not object")
  }
}

sealed trait Parent 
case object GetOne extends Parent
case object GetTwo extends Parent
check[Parent]() // compiles

sealed trait Parent
case object GetOne extends Parent
case object Two extends Parent
check[Parent]() // doesn't compile

sealed trait Parent
case object GetOne extends Parent
case class GetTwo() extends Parent
check[Parent]() // doesn't compile
import shapeless.tag.@@ 
import singleton.ops.{Require, StartsWith} 

trait StartsWithGet[S] 
object StartsWithGet { 
  implicit def mkStartsWithGet[S <: String](implicit 
    startsWith: Require[S StartsWith "Get"]
  ): StartsWithGet[Symbol @@ S] = null 
}