我想在下面的商店中拍打读取和/或写入特征。为此,我需要为模式或函数提供默认的类似null的值,然后在运行时检查它们。这是为了允许读,读,写和只写存储。这些特征将定义reader
和/或writer
,这就是全部。
这看起来像是:
//read only, exception if someone tried to write with it
val rStore = new Store[SomeType](sc, readSchema) with SomeReadTrait
//write only, this would leave inSchema as null-ish so I can check if readfrom is called.
val wStore = new Store[SomeType](sc, outSchema = writeSchema) with SomeWriteTrait
// read/write
val rwStore = new Store[SomeType](sc, readSchema, writeSchema) with SomeReadTrait with SomeWriteTrait
// another way to do read/write
val rwStore = new Store[SomeType](sc, readSchema, writeSchema) with SomeReadWriteTrait
但我无法弄清楚如何在构造函数中创建默认的null-ish值以及内部函数def的默认null-ish值。
我或许可以使用三种抽象类型来处理这个问题,但有没有办法像下面这样做以保持代码DRY。我不在乎是否检查读取器/写入器功能(查看特性是否由特性提供)或模式(查看构造时给出的非null值)或两者兼而有之。
abstract class Store[T](sc: SparkContext, inSchema: Schema = ????, outSchema: Schema = ????){
/** Reader function that reads from the location into the T and returns it, supplied by a Read trait*/
def reader: (SparkContext, Schema, String) => T = ????
/** Writer function, supplied in a Write trait */
def writer: (SparkContext, Schema, String, T) => ????
def readFrom(source: String): T = {
if (reader != ????) reader(sc, inSchema, source) else throw new IllegalArgumentException("Store: readFrom called but there is no reader function has been defined")
}
def writeTo(collection: T, dest: String): Unit = {
if (writer != ????) writer(sc, outSchema, dest, collection) else throw new IllegalArgumentException("Store: writeTo has been called but there is no writer function")
}
}
答案 0 :(得分:3)
这是实现你想要的一种奇怪的方式。如果outSchema
仅在WriteTrait
混入时相关,而inSchema
仅在ReadTrait
混入时相关,那么为什么它们不属于特征但是其他一些课程的一部分?如果你把它们作为特征的一部分,你可以让编译确保一切正常,而不是抛出IllegalArgumentException
。
trait SomeReadTrait[T] {
val inSchema: Schema
val context: SparkContext
def reader(sc: SparkContext, s: Schema, source: String): T = ???
def readFrom(source: String): T = reader(context, inSchema, source)
}
trait SomeWriteTrait[T] {
val outSchema: Schema
val context: SparkContext
def writer(sc: SparkContext, s: Schema, dest: String, collection: T) = ???
def writeTo(collection: T, dest: String) = writer(context, outSchema, dest, collection)
}
trait SomeReadWriteTrait[T] extends SomeReadTrait[T] with SomeWriteTrait[T]
class ReadStore[T](val context: SparkContext, val inSchema: Schema) extends SomeReadTrait[T]
class WriteStore[T](val context: SparkContext, val outSchema: Schema) extends SomeWriteTrait[T]
class ReadWriteStore[T](val context: SparkContext, val inSchema: Schema, val outSchema: Schema) extends SomeReadWriteTrait[T]
这不是你想要的吗?
答案 1 :(得分:0)
借助@ DCKing的帮助,我认为这就是我所需要的。没有抽象类 - 所有特征。有一个根特征定义了readFrom或writeTo的属性和一个方法。扩展特征定义读取或写入的类型以及读取器或写入器。现在为了扩展它,我们只为特定数据类型创建一个新的读或写特征,只写一个受保护的函数。很干。使用String作为各种类型的替代品。
trait RT[T]{
val sc: String
val inSchema: String
protected def reader(sc: String, s: String, source: String): T
def readFrom(source: String): T = reader(sc, inSchema, source)
}
trait StringReadTrait extends RT[String]{
protected def reader(sc: String, s: String, source: String): String = {println("StringReadTrait#reader called, sc: "+sc+" s: "+s+" source: "+source); "StringReadTrait#reader"}
}
trait WT[T]{
val sc: String
val outSchema: String
protected def writer(sc: String, s: String, dest: String, collection: String): Unit
def writeTo(collection: String, dest: String) = writer(sc, outSchema, dest, collection)
}
trait StringWriteTrait extends WT[String]{
protected def writer(sc: String, s: String, dest: String, collection: String) = {println("writer called, sc: "+sc+" s: "+s+" dest: "+dest+" collection: "+collection)}
}
trait StringReadWriteTrait extends StringReadTrait with StringWriteTrait
class ReadStore(val inSchema: String, val sc: String) extends StringReadTrait
class WriteStore(val outSchema: String, val sc: String) extends StringWriteTrait
class ReadWriteStore(val inSchema: String, val outSchema: String, val sc: String) extends StringReadWriteTrait