I have something like this:
abstract class HaveData{
val data:String
}
class HD1 extends HaveData{
val data = "HD1 data"
}
class HD2 extends HaveData{
val data = "HD2 data"
object InnerHD extends HD1{
def prt = println(data)
}
}
I want to print "HD2 data" not "HD1 data", how to do that?
I may turn InnerHD to a class and provide data as a param but is there a better way?
For this kind of situations you can use a self-type, for this specific problem, you do not need to add a different type.
abstract class HaveData {
def data: String
}
class HD1 extends HaveData {
override val data = "HD1 data"
}
class HD2 extends HaveData { self => // Alias to this in the HD2 level.
override val data = "HD2 data"
object InnerHD extends HD1 {
def prt(): Unit = {
println(self.data)
}
}
}
(new HD2).InnerHD.prt()
// HD2 data
You can also use
def prt = println(HD2.this.data)
Related
I need to write two functions to get the output format and the output index for file conversion. As part of this, I wrote a TransformSettings class for these methods and set the default value. And in the transformer class, I created a new object of TransformSettings class to get the default values for each job run. Also, I have another class called ParquetTransformer that extends Transformer where I want to change these default values. So I implemented like below.
class TransformSettings{
def getOuputFormat: String = {
"orc"
}
def getOuputIndex(table: AWSGlueDDL.Table): Option[String] = {
table.StorageDescriptor.SerdeInfo.Parameters.get("orc.column.index.access")
}
}
class Transformer{
def getTransformSettings: TransformSettings = {
new TransformSettings
}
def posttransform(table: AWSGlueDDL.Table):Dateframe ={
val indexAccess = getTransformSettings.getOuputIndex(table: AWSGlueDDL.Table)
........
}
}
class ParquetTransformer extends Transformer{
override def getTransformSettings: TransformSettings = {
val transformSettings = new TransformSettings {
override def getOuputFormat: String = {
"parquet"
}
override def getOuputIndex(table: AWSGlueDDL.Table): Option[String] = {
table.StorageDescriptor.SerdeInfo.Parameters.get("parquet.column.index.access")
}
}
}
}
Is there a way to avoid creating a brand new object of TransformSettings in Transfomer class every time this is called?
Also is there a way to rewrite the code using Scala value class?
As #Dima proposed in the comments try to make TransformSettings a field / constructor parameter (a val) in the class Transformer and instantiate them outside
class TransformSettings{
def getOuputFormat: String = {
"orc"
}
def getOuputIndex(table: AWSGlueDDL.Table): Option[String] = {
table.StorageDescriptor.SerdeInfo.Parameters.get("orc.column.index.access")
}
}
class Transformer(val transformSettings: TransformSettings) {
def posttransform(table: AWSGlueDDL.Table): DataFrame ={
val indexAccess = transformSettings.getOuputIndex(table: AWSGlueDDL.Table)
???
}
}
val parquetTransformSettings = new TransformSettings {
override def getOuputFormat: String = {
"parquet"
}
override def getOuputIndex(table: AWSGlueDDL.Table): Option[String] = {
table.StorageDescriptor.SerdeInfo.Parameters.get("parquet.column.index.access")
}
}
class ParquetTransformer extends Transformer(parquetTransformSettings)
You don't seem to need value classes (... extends AnyVal) now. They are more about unboxing, not about life-cycle management. TransformSettings and Transformer can't be value classes because they are not final (you're extending them in class ParquetTransformer extends Transformer... and new TransformSettings { ... }). By the way, value classes have many limatations
https://failex.blogspot.com/2017/04/the-high-cost-of-anyval-subclasses.html
https://github.com/scala/bug/issues/12271
Besides value classes, there are scala-newtype library in Scala 2 and opaque types in Scala 3.
trait paymentTasks{
def calculatePayment()
def getData()
}
class paymentcalculator{
override def calculatePayment() ={
//Implementation }
}
override defGetData() ={
}
}
How do I call the method to keep the code less dependent and don't want to use new keyword
class MyApp{
val payment = new paymentcalculator
//I don't want to instantiate like this wants this to be decoupled
}
Please suggest how do I implement this ,also new Changes in future can be done without changing existing code.Also,suggest if doing this functionally would be more effective
If you want compile-time selection then just put the code into an object
trait PaymentTasks {
def calculatePayment()
def getData()
}
object PaymentCalculator extends PaymentTasks {
def calculatePayment() = ???
def getData() = ???
}
class MyApp {
val payment = PaymentCalculator.calculatePayment()
}
If you want run-time selection than the best way is to use dependency injection and create the payment object at the top level and pass it down to the code that requires it.
object SimplePaymentCalculator extends PaymentTasks
object ComplexPaymentCalculator extends PaymentTasks
class MyApp {
def myImplementation(tasks: PaymentTasks) = {
val payment = tasks.calculatePayment()
}
val payment =
if (???) {
SimplePaymentCalculator
} else {
ComplexPaymentCalculator
}
myImplementation(payment)
}
Is there another way than using a subclass of the Controller to benefit from the injected Play Framework pooled database parameter db ?
This is what the Documentation recommends :
class ScalaControllerInject #Inject()(db: Database) extends Controller {
def index = Action {
var outString = "Number is "
val conn = db.getConnection()
...
Ok(outString)
}
}
However I would like to have another class querying the database. This is because I am not using a subclass of the Controller class : I am using a websocket Actor.
This something I would like to aim for:
object MyWebSocketActor {
def props(out: ActorRef) = Props(new MyWebSocketActor(out))
}
class MyWebSocketActor(out: ActorRef) extends Actor {
val gson = ToolSingleton.getInstance().getGsonTool()
def receive = {
case msg: String => {
val dbm=(new DbManager(... )). query(msg)
}
}
}
class DbManager #Inject()(db: Database) extends /* ? */ {
def query(s : String) {
var outString = "Number is "
val conn = db.getConnection()
...
}
}
How should I extend DbManager in order to use the function query from my actor MyWebSocketActor?
I made a lexer based on Parsing M-Expressions in Scala with combinators.
import scala.util.parsing.combinator.lexical._
import scala.util.parsing.combinator.token._
trait MyTokens extends Tokens {
case class Id(chars: String) extends Token
case class Num(chars: String) extends Token
}
class MyLexical extends Lexical with MyTokens {
def whitespace = rep(whitespaceChar)
def token: Parser[Token] = (
rep1(letter) ^^ { case charList => Id(charList mkString "") }
| rep1(digit) ^^ { case charList => Num(charList mkString "") }
)
}
object Main extends App {
val lexical = new MyLexical
val scanner = new lexical.Scanner("abc012def345")
def tokenList(s: lexical.Scanner): List[lexical.Token] =
if (s.atEnd) Nil
else s.first :: tokenList(s.rest)
println(tokenList(scanner))
}
It worked well resulting in List(Id(abc), Num(012), Id(def), Num(345)). However, the function tokenList should be a method of Scanner to call it as scanner.tokenList. In order to achieve it, it seems that the inner class MyLexical.Scanner should be overriden. Is it possible? If you can, how to do it?
I don't think you can add a method to inner class, but you can use implicit conversion to achieve similar result. It would look like following:
object ScannerImplicits {
implicit class BetterScanner(scanner: MyLexical.Scanner) {
def tokenList(s: MyLexical.Scanner): List[MyLexical.Token] = {
if (s.atEnd) Nil
else s.first :: tokenList(s.rest)
}
}
}
Than you'll be able to write
import ScannerImplicits ._
new lexical.Scanner("abc012def345").tokenList
As far as I understand it, Scala creates an anonymous class if I create a class using the new keyword and follow the class name with a constructor:
class MyClass {
def doStuff() {
// ...
}
}
val mc = new MyClass {
doStuff()
}
The nice thing being that all the code in the constructor is in the scope of the new object.
Is there a way I can reproduce this syntax where the class is created by a factory method rather than the new keyword? i.e. make the following code work:
val mf = new MyFactory
val mc = mf.MyClass {
doStuff()
}
I can't find a way to do it but Scala has so much to it that this might be pretty easy!
Using an import as suggested by #Ricky below I can get:
val mf = MyFactory;
val mc = mf.MyClass
{
import mc._
doStuff()
}
(Where the blank line before the block is needed) but that code block is not a constructor.
You can do this, but you still have to keep the new keyword, and create the nested class as a path-dependent type:
class Bippy(x: Int) {
class Bop {
def getIt = x
}
}
val bip = new Bippy(7)
val bop = new bip.Bop
bop.getIt // yields 7
val bop2 = new bip.Bop{ override def getIt = 42 }
bop2.getIt // yields 42
I don't think it's possible. However, a common pattern is to add a parameter to factory methods which takes a function modifying the created object:
trait MyClass {
var name = ""
def doStuff():Unit
}
class Foo extends MyClass {
def doStuff() { println("FOO: " + name) }
}
trait MyClassFactory {
def make: MyClass
def apply( body: MyClass => Unit ) = {
val mc = make
body(mc)
mc
}
}
object FooFactory extends MyClassFactory {
def make = new Foo
}
You can then create and modify instance with a syntax close to your example:
val foo = FooFactory { f=>
f.name = "Joe"
f.doStuff
}
It sounds like you're just looking to mix in a trait. Instead of calling myFactoryMethod(classOf[Foo]] which ideally would do (if Scala permitted it):
new T {
override def toString = "My implementation here."
}
you can instead write
trait MyImplementation {
override def toString = "My implementation here."
}
new Foo with MyImplementation
However, if you are just looking to get the members of the new object accessible without qualification, remember you can import from any stable identifier:
val foo = new Bar
import foo._
println(baz) //where baz is a member of foo.