我有以下内容,我为不同的数据方案设置信息和提取器:
trait DataScheme {
type Type <: List[Any]
class ExtractorMethods(ticker: String, dataList: List[Type]) {
def getDatetime(datum: Type): Date = new Date(datum(columnIndex(Names.datetime)).toString)
def upperDatum(date: Date): Type = dataList.minBy(datum => getDatetime(datum) >= date)
def lowerDatum(date: Date): Type = dataList.maxBy(datum => getDatetime(datum) <= date)
}
}
trait IndexScheme extends DataScheme {
type Type = (Date, Double, Double, Double, Double, Long)
class ExtractorMethods(ticker: String, dataList: List[Type]) extends super.ExtractorMethods(ticker: String, dataList: List[Type]){
def testing12(int: Int):Int = 12
val test123 = 123
}
}
我希望扩展DataScheme以使用其ExtractorMethods方法(例如lowerDatum),但也有自己的方法(例如testing12)。
数据元素列表有一个类定义:
class Data[+T <: DataScheme](val ticker: String, val dataList: List[T#Type], val isSorted: Boolean)
(implicit m: Manifest[T], mm: Manifest[T#Type]) extends Symbols {
def this(ticker: String, dataList: List[T#Type])(implicit m: Manifest[T], mm: Manifest[T#Type]) = this(ticker, dataList, false)(m: Manifest[T], mm: Manifest[T#Type])
val dataScheme: T
val extractorMethods = new dataScheme.ExtractorMethods(ticker, dataList.asInstanceOf[List[dataScheme.Type]])
}
Data类应该可以访问方案的ExtractorMethods中的方法,以便可以通过已定义的Data实例在主程序中使用它们。例如,如果sortedData是Data [IndexScheme]的实例,则以下工作:
val lowerDatum = sortedData.extractorMethods.lowerDatum(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2010-03-31 00:00:00"))
但这不是:
val testing = sortedData.extractorMethods.testing12(123)
因为'测试123不是sortedData.dataScheme.extractorMethods'的成员。所以我的问题是如何使DataScheme的Subtraits中的ExtractorMethods的子类像IndexScheme一样可以访问?如何使用Manifest和TypeTag?感谢。
答案 0 :(得分:0)
因此,您希望泛型类Data [DataScheme]或Data [IndexScheme]能够访问已经参数化的数据类型的方法。您已经尝试过几种不同的方式,从代码中的证据开始。
要回答您的上一个问题 - 在这种特殊情况下,清单无法帮助,而TypeTag只是答案的一部分。如果您真的想这样做,可以使用mirrors。
但是,您必须对代码进行一些更改。 Scala只有实例方法; Scala中没有静态方法之类的东西。这意味着您只能使用反射来调用类,特征或对象的实例上的方法。你的特征是抽象的,无法实例化。
我无法告诉你如何清理你的代码,因为你在这里粘贴的东西有点乱,并且你已经尝试了很多不同的东西。我可以告诉你的是如何使用更简单的类来完成它:
import scala.reflect.runtime.universe._
class t1 {
class Methods {
def a = "a"
def b = "b"
}
def methods = new Methods
}
class t2 extends t1 {
class Methods extends super.Methods {
def one = 1
def two = 2
}
override def methods = new Methods
}
class c[+T <: t1](implicit tag: TypeTag[T]) {
def generateT = {
val mirror = runtimeMirror(getClass.getClassLoader)
val cMirror = mirror.reflectClass(typeOf[T].typeSymbol.asClass)
cMirror.reflectConstructor(typeOf[T].declaration(nme.CONSTRUCTOR).asMethod)
}
val t = generateT().asInstanceOf[T]
}
val v1 = new c[t1]
val v2 = new c[t2]
如果你运行它,你会发现v1.t.methods
只给你一个只有方法a和b的类,但是v2.t.methods
给了一个方法一和二的类。
这真的不是如何做到这一点 - 为这种工作寻求反思显示出一个非常破碎的模型。但我猜这是你的事。
我坚持下面所说的话。您应该使用伴随对象的隐式转换(以及可能的隐式参数)。按照设计的方式使用Scala的类型系统 - 你一直在与它作斗争。
原始回答
好吧,我首先要说的是,我永远不会按照你这样做的方式做事;它看起来非常复杂。但你可以通过
按照你的方式做你想做的事这是一个非常简化的例子:
trait t1 {
class Methods {
def a = "a"
def b = "b"
}
def methods = new Methods
}
trait t2 extends t1 {
class Methods extends super.Methods {
def one = 1
def two = 2
}
override def methods = new Methods
}
class c1 extends t1
val v1 = new c1
// v1.methods.a will return "a", but v1.methods.one does not exist
class c2 extends c1 with t2
val v2 = new c2
// v2.methods.a returns "a" and v2.methods.one returns 1
我可以通过像这样定义 c1 来更密切地复制你的作案手法:
class c1 extends t1 {
val myMethods = methods
}
在这种情况下,v1.myMethods
只有 a 和 b 方法,但v2.myMethods
会有 a ,< strong> b ,一个和两个。
您应该能够看到如何使其适应您自己的班级和特质结构。我知道我的例子中没有任何复杂的类型逻辑,但你比我更了解你想要实现的目标。我只是想展示一个简单的机制。
但是老兄,这样可以让你的生活变得困难......
修改强>
关于你的方法,无论是小规模还是大规模,我都可以说很多事情。我将限制自己说两件事:
您无法在数据类中执行您要执行的操作,因为它是抽象的。您不能强制Scala用特定类型神奇地替换非特定类型的未初始化的抽象方法,只需使用类型注释乱丢所有内容即可。您只能通过提供特定类型的具体类来解决此问题。
您应该使用隐式转换执行此操作。 Implicits可以帮助您以错误的方式执行此操作,但也可以帮助您以正确的方式执行此操作。哦,并使用伴侣对象,无论是暗示还是持有工厂(或机器人)。