gpt4 book ai didi

scala - 如何构建泛型类型的匿名实例?

转载 作者:行者123 更新时间:2023-12-04 21:40:03 26 4
gpt4 key购买 nike

考虑这个简单的类:

class MyClass(p: (String, String) *) {
val params: Map[String, String] = p.toMap
}

还有一个扩展它的类:
class SomeOtherClass(p: (String, String) *) extends MyClass(p: _*)

我想从 MyClass 中删除构造函数避免在扩展它的所有内容中携带初始化参数(可能是许多类型)。相反,我更喜欢扩展 MyClass 的类型的伴生对象。继承某种构建器方法。
class MyClass {
val param = Map.empty[String, String] // some member with a default value
}

trait MyClassBuilder[A <: MyClass] {
def apply(p: (String, String) *): A = ???
}

基本上 apply应该做这样的事情:
new A {
override val param = p.toMap
}

显然,上面的代码是行不通的。这个想法是像这样使用子类型:
class SomeOtherClass extends MyClass
object SomeOtherClass extends MyClassBuilder[SomeOtherClass] {
// object specific things..
}

然后 SomeOtherClass将依赖于继承的 apply创建自身实例的方法。反射或宏似乎可以实现这样的事情,但我真的不知道。明确地说,我想要像 SomeOtherClass 这样的客户端代码根本不需要构造函数,这就是为什么我想探索在泛型类型上创建匿名类的原因。可能不是 SomeOtherClass生成的,它可以是任何扩展 MyClass .

最佳答案

这可能会帮助您:

import scala.reflect._
abstract class MyClassBuilder[A <: MyClass: ClassTag] {
def apply() = classTag[A].runtimeClass.newInstance.asInstanceOf[A]
}

你可能会发现我没有通过 (String, String) *在这里,因为它们对于实例化是多余的。无论如何,您可以访问整个 A的实例在这里,所以至少你可以改变 param实例化后。这并不完全是您想要的 - 因为您似乎正在寻找一种额外扩展 SomeOtherClass 的方法在运行时。但是,在 scala 中创建新类型的运行时是不可能的,但您可能会将其视为原型(prototype) - 只需获取 SomeOtherClass 实例并在 apply() 内变异一次:
import scala.reflect._
object Ctx {
class MyClass {
private[Ctx] var _param = Map.empty[String, String]
def param = _param
}

abstract class MyClassBuilder[A <: MyClass: ClassTag] {
def apply(p: (String, String) *) = {
val i = classTag[A].runtimeClass.newInstance.asInstanceOf[A]
i._param = Map(p: _*)
i
}
}
}

scala> class MySpecialClass extends Ctx.MyClass
defined class MySpecialClass

scala> object MySpecialBuilder extends Ctx.MyClassBuilder[MySpecialClass]
defined module MySpecialBuilder

scala> MySpecialBuilder("A" -> "b")
res12: MySpecialClass = MySpecialClass@2871ed4a

scala> res12.param
res13: scala.collection.immutable.Map[String,String] = Map(A -> b)

否则你必须处理编译时反射。

一个有趣的选择是 extensible records (Shapeless2) - 它们实际上允许您逐个构建新类型,但您必须处理 HList而不是在那里上课:
import shapeless._ ; import syntax.singleton._ ; import record._
import shapeless.ops.record.Updater
import scala.reflect.runtime.universe._

val param = Witness("param")
val someFunW = Witness("someFun")

//defining classess (instead of "class MyClass")

type Param = Map[String, String] with KeyTag[param.T, Map[String, String]]
type SomeFun = (String => String) with KeyTag[someFunW.T, (String => String)]
type MyClass = Param :: HNil
type MySpecialClass = SomeFun :: MyClass

def someFun(s: String) = s + "A"

//defining default values (instead of "val param = ...")

def newMyClass[T <: HList : TypeTag]: T = (
if (typeTag[T] == typeTag[MyClass])
(param ->> Map.empty[String, String]) :: HNil
else if (typeTag[T] == typeTag[MySpecialClass])
(someFunW ->> someFun _) :: newMyClass[MyClass]
else HNil
).asInstanceOf[T]

//Defining builder
def buildWithParam[T <: HList: TypeTag](p: Map[String, String])(implicit ev: Updater[T, Param])
= newMyClass[T] + ("param" ->> p)

scala> buildWithParam[MySpecialClass](Map("a" -> "v"))
res6: ... = <function1> :: Map(a -> v) :: HNil

scala> res6("someFun").apply("a")
res7: String = aA

scala> buildWithParam[MyClass](Map("a" -> "v"))
res8: ... = Map(a -> v) :: HNil

关于scala - 如何构建泛型类型的匿名实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28801462/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com