Reputation: 63062
Consider the "constant" value: DefaultEncoding. Typically we would add it to the companion object:
object Strlen {
val DefaultEncoding = "ISO-8859-1"
..
}
However, we are compelled to avoid the use of a companion object because Strlen is required to be a case class to correspond to code structures/conventions in a significant existing codebase:
case class Strlen(child: Expression, encoding : Expression) extends UnaryExpression with LengthExpression {
val DefaultEncoding = "ISO-8859-1" // This will not be isible in the following constructor
def this(child: Expression) = this(child, new Literal(DefaultEncoding, StringType))
So then would there be any way to achieve compartmentalization of the DefaultEncoding 'constant' within the case class?
Update From suggestion by wingedsubmariner, I tried the following within the case class:
def DefaultEncoding = "ISO-8859-1"
However it does not compile
[info] Compiling 1 Scala source to /shared/spark-master/sql/catalyst/target/scala-2.10/classes...
[error] /shared/spark-master/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/stringOperations.scala:253: not found: value DefaultEncoding
[error] def this(child: Expression) = this(child, new Literal(/* StrConstants. */DefaultEncoding, StringType))
[error]
Upvotes: 2
Views: 6532
Reputation: 8534
Writing a custom companion object for a case class
won't prevent the compiler from providing the default helper methods for the case class.
trait Expression
trait UnaryExpression extends Expression
trait LengthExpression extends Expression
trait Typ
case object StringType extends Typ
case class Literal(val encoding: String, val typ: Typ) extends Expression
case class StrLen(child: Expression, encoding: Expression) extends UnaryExpression with LengthExpression {
def this(child: Expression) = this(child, new Literal(StrLen.DefaultEncoding, StringType))
}
object StrLen {
val DefaultEncoding = "ISO-8859-1"
def apply(child: Expression): StrLen = apply(child, new Literal(StrLen.DefaultEncoding, StringType))
}
case object ExampleExpression extends Expression
println(StrLen(ExampleExpression))
// --> StrLen(ExampleExpression,Literal(ISO-8859-1,StringType))
println(new StrLen(ExampleExpression))
// --> StrLen(ExampleExpression,Literal(ISO-8859-1,StringType))
def isProduct[T <: Product] {}
isProduct[StrLen]
The default apply
is still provided by the compiler (and used in def apply(child: Expression
), StrLen
still extends Product
and toString
still does the right thing.
The custom constructor def this(child: Expression)
is probably unnecessary, as you can use the single-parameter apply
instead.
Upvotes: 4
Reputation: 13667
You can use companion objects with case classes. If you declare an object with the same name in the same compilation unit (usually the same file) it will be treated as the case class's companion object and have the usual case class companion object methods, e.g. unapply
, added to it.
The other option is to declare DefaultEncoding
as a def
. Because field access is always done through accessors in Scala this doesn't have any performance penalty.
Upvotes: 3