使用默认值的Scala构造函数

使用默认值的Scala构造函数,scala,constructor,null,Scala,Constructor,Null,我想在下面的存储中添加一个读写特征。为此,我需要为模式或函数设置默认的类似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

我想在下面的存储中添加一个读写特征。为此,我需要为模式或函数设置默认的类似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值

我可能可以用三种抽象类型来处理这个问题,但是有没有一种方法可以像下面这样保持代码的干爽。我不在乎检查是针对读写器/写入器函数(查看是否由trait提供了非空ish函数)或模式(以查看构造时给出的哪些值为非空ish值)或两者兼而有之


这是一个奇怪的方式来实现你想要的。如果
outSchema
仅在
WriteTrait
混入时相关,而
inSchema
仅在
ReadTrait
混入时相关,那么为什么它们不是traits的一部分,而是其他类的一部分?如果你让它们成为trait的一部分,你可以让编译器确保一切正常,而不是到处抛出
IllegalArgumentException
s

 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]

这不是你想要的吗?

在@DCKing的帮助下,我想这就是我需要的。没有抽象类——所有特性。有一个根特征定义了属性和一个readFrom或writeTo方法。扩展特征定义读写类型以及读写器。现在为了扩展它,我们只需为特定的数据类型创建一个新的读或写特性,只需编写一个受保护的函数。相当干燥。使用字符串作为各种类型的替代项

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

我可以使用默认模式值
inSchema:Schema=null.asInstanceOf[Schema]
,并在
readFrom
writeTo
中检查该值。但是仍然无法理解如何拥有一个只定义
编写器
读取器
功能的特性。我可以创建定义读写器的特性,并在调用错误的异常时抛出异常,但这是一个运行时错误,因为我想把它变成编译时错误。我对Scala有3周的了解,这就是为什么我要问这些问题:-)抽象类的原因是为了在构造时间,以保证编写器或读取器由类的特征提供,或者保留为空,以便在运行时检查一致性。使用您的方法,sc永远不会传入。事实上这不会编译吧?因此,您必须将sc放在每个类构造函数中,并且按照惯例,因为没有抽象类提供模板。更多评论…我还需要提供一个已经理解T类型参数的特性,因为读写器将特定于该类型。-不过,将模式放在trait中似乎是一种更干净的方法。使这些特征类型具体化是非常重要的easy@pferrel我的回答有点马虎,我纠正了它,这样至少SparkContext是存在的。如果你不想使用泛型,我认为最好你问一个不同的问题:)NP,我应该能做那么多;-)我确实想使用泛型,因为要编写的类型很多。但是,每个特定类型都有一个特定的实现。如果readFrom和writeTo使用泛型类型,那么它们可以被继承,因此抽象类就是我要去的地方。也许我可以用特定类型的扩展的基本泛型特征来实现这一点。类型特定特征扩展了仅提供
读卡器
写卡器
的基本特征,并用于扩展ReadStore/WriteStore?我要把贝壳修补一下,看看能不能用。这些特质似乎是对的,但我还不明白。
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