Unable to call an instance method before constructor in scala - scala

I have some code like the following:
class Test(var f1 : String) {
def this(a : Int) {
this(makeStr(a))
}
private def makeStr(a : Int): Unit = {
"ABC" + a
}
}
The error I get is: not found: value makeStr.
It seems like the scala compiler cannot see the makeStr method in the constructor. It seems to be quite different from Java where it is doable. Does anyone know what is the right way to initialize the instance fields which requires some methods to compute the values?

You can't call instance methods before the primary constructor has run. You can declare makeStr as a method in the companion object so you can run it before the primary constructor. Also not that it should return String, not Unit as in your code.
class Test(var f1 : String) {
def this(a : Int) {
this(Test.makeStr(a))
}
override def toString = s"Test($f1)"
}
object Test{
private def makeStr(a : Int): String = {
"ABC" + a
}
}
new Test(1) //res0: Test = Test(ABC1)
It's a bit more idiomatic to define factory methods in the companion object instead of using multiple constructors though, as the other answers mention.

If I understand correctly, you are trying to create a class with multiple constructors. In scala, the best practice is different from Java.
You should first create a class and then its companion object in order to implement different constructors.
//your class
class Test(val f1: String)
//its companion object
object Test {
def apply(f1: String): Test = new Test(f1)
def apply(f1: Int): Test = new Test("ABC" + f1)
}
You can simply test the code above by the following code:
object Main {
def main(args: Array[String]): Unit = {
val testInt: Test = Test(1)
val testString: Test = Test("1")
println(testInt.f1)
println(testString.f1)
}
}

I feel in this case that the best solution would be to use factory methods instead of auxi constructor.
So you can define your constructor private and provide factory apply methods in companion object:
scala> :paste
// Entering paste mode (ctrl-D to finish)
class Test private(var f1 : String)
object Test {
def apply(i: String) = new Test(i)
def apply(s:Int) = new Test(makeStr(s))
def makeStr(s: Int) = {
"ABC" + s } }
// Exiting paste mode, now interpreting.
defined class Test
defined object Test
For more infor refer

Related

Using mixin composition with functions in scala

I'm trying to use mixin composition using functions, but I have an error in the apply method of obj object:
Overriding method apply in trait t of type (s: String)String; method apply needs abstract override modifiers.
How to solve this error and which is the correct implementacion?
trait t extends Function1[String,String] {
abstract override def apply(s: String): String = {
super.apply(s)
println("Advice" + s)
s
}
}
object MixinComp {
def main(args: Array[String]) {
val obj = new Function1[String, String] with t {
override def apply(s: String) = s
}
println(obj.apply("Hi"))
}
}
Your immediate problem (the reason it complains about the error) is that you can't have an abstract call in your linearization flow (your t.apply calls super.apply, which is abstract).
Also, the apply method you define in the top level anonymous class overrides everything, and does not call super, making the t being mixed in completely irrelevant.
Something like this would solve both problems:
trait t extends Function1[String,String] {
abstract override def apply(s: String): String = {
println("Advice" + s)
super.apply(s) // I rearranged this a little, because it kinda makes more sense this wat
}
}
// Note, this extends `Function1`, not `t`, it, just a "vanilla" Function1
class foo extends Function1[String, String] {
def apply(s: String): String = s
}
// Now I am mixing in the t. Note, that the apply definition
// from foo is now at the bottom of the hierarchy, so that
// t.apply overrides it and calls it with super
val obj = new foo with t
obj("foo")
You won't need to use the abstract modifier in your t trait definition, if you don't call the super.apply. And in this particular case I dont see any need for calling super.apply as Function1's apply is abstract. You probably need custom apply implementations. The following code should work.
trait t extends Function1[String, String] {
override def apply(s: String): String = {
// super.apply(s)
println("Advice" + s)
s
}
}
Case1: use the overridden apply method in t trait:
val obj = new Function1[String, String] with t {}
obj.apply("hello") // prints: Advicehello
Case 2: override the apply method in t trait in an anonymous class:
val obj = new Function1[String, String] with t {
override def apply(s: String): String = s
}
obj.apply("hello") // prints hello

Spray JSON: How to get implicitly declared objects into read and write methods?

I am currently struggling with spray-json writing a protocol for my data model. For deserialization of JSON data to my data transfer objects, a DAO has to be contacted to check if an appropriate object exists, otherwise a DeserializationException should be thrown.
So far, I have the following:
object MyJsonProtocol extends DefaultJsonProtocol {
implicit object MyDtoJsonFormat extends RootJsonFormat[MyDto] {
override def write(obj: MyDto): JsValue = // Serialization implementation
override def read(json: JsValue): MyDto = {
// parse the JSON, get some parameters, let them be a, b, c
dtoLookup(a, b, c) match {
case Some(dto: MyDto) => dto
case None => throw new DeserializationException("Cannot retrieve object from DAO")
}
}
}
def dtoLookup(a: SomeType, b: SomeOtherType, c: YetAnotherType)(implicit dao: MyDAO): Option[MyDto] = {
// lookup the MyDTO with the dao instance
}
}
My test looks like the following:
class MyJsonProtocolTest extends FlatSpec with Matchers {
implicit val MyDAO = // some test instance, can be a mock object
"The protocol" should "serialize a DTO" in {
val dto: MyDTO = ...
dto.toJson.compactPrint should be("{...}")
}
}
However, the compiler complains that it cannot find the implicit MyDAO when trying to compile the MyJSONProtocol. In When testing Spray services with Scalatest, how to introduce implicit values? I asked yesterday, I was suggested to pass in the implicit parameter directly into the method, but I cannot do this here because the read method is defined in the RootJsonFormat.
When I call the dtoLookup method directly from my test code, it succeeds.
So, how do I get the MyDAO instance into my special JSON format?
One option is to make the implicit parameter a constructor parameter to one of the classes being used. This might require that you turn one of your objects into a class. Then you can make an get method on the companion object of that class that uses an implicit in scope to construct the class with the desired argument.
This doesn't really have to do with spray or scalatest, rather it's just an issue with implicits and implicit scope. Here's a simplified version:
object MyJsonProtocol {
implicit object MyDtoJsonFormat {
def read(x: Int) = dtoLookup
}
def dtoLookup(implicit x: Int) = x + 1
}
And you might consider changing that to:
class MyJsonProtocol(implicit x: Int) {
implicit object MyDtoJsonFormat {
def read(x: Int) = dtoLookup
}
def dtoLookup = x + 1
}
object MyJsonProtol {
def get(implicit x: Int) = new MyJsonProtocol
}
And then you can use this with an implicit in scope:
class MyJsonProtocolTest {
implicit val x = 5
val proto = MyJsonProtol.get
val myReadValue = proto.MyDtoJsonFormat.read //6
}
You can read about the rules for implicit scopes here, especially relevant might be the "Where do Implicits Come From" section.

Implicit conversion with implicit parameter

I'm implementing a Java interface with a lot of methods with Object parameters, which in my case are really Strings containing user names:
public interface TwoFactorAuthProvider {
boolean requiresTwoFactorAuth(Object principal);
... //many more methods with the same kind of parameter
}
I'm trying to use implicit conversion to convert these to User objects in my implementation:
class TwoFactorAuthProviderImpl(userRepository: UserRepository)
extends TwoFactorAuthProvider {
def requiresTwoFactorAuth(user: User): Boolean = {
...
}
}
When I define the conversion in the companion object of my class, it is picked up just fine and my class compiles:
object TwoFactorAuthProviderImpl {
implicit def toUser(principal: Any): User = {
null //TODO: do something useful
}
}
However, to be able to do the conversion, I need access to the user repository, which the TwoFactorAuthProviderImpl instance has, but the companion object does not. I thought I could possibly use an implicit parameter to pass it:
implicit def toUser(principal: Any)(implicit repo: UserRepository): User = {
val email = principal.asInstanceOf[String]
repo.findByEmail(email)
}
But with the implicit parameter, the conversion is no longer picked up by the compiler (complaining that I'm not implementing the interface).
Is there a way to get the implicit conversion that I want, or is this outside the scope of what you can do with implicits?
This should work just fine - can you supply the exact compilation error? Not implementing what interface? It looks like you would have to declare as follows:
class TwoFactorAuthProviderImpl(implicit userRepository: UserRepository)
Here's an example for the REPL to show that implicits can have implicits; I'm using paste mode to ensure that module X is the companion object of the class X
scala> :paste
// Entering paste mode (ctrl-D to finish)
case class X(i: Int, s: String)
object X { implicit def Int_Is_X(i: Int)(implicit s: String) = X(i, s) }
// Exiting paste mode, now interpreting.
defined class X
defined module X
scala> val i: X = 4
<console>:9: error: value X is not a member of object $iw
val i: X = 4
^
But if we add an implicit string in scope
scala> implicit val s = "Foo"
s: java.lang.String = Foo
scala> val i: X = 4
i: X = X(4,Foo)
Implicits advice
Don't go overboard with implicit conversions - I think you are going too far in this sense - the principal is implicitly a mechanism by which you can discover a user, it is not implicitly a user itself. I'd be tempted to do something like this instead:
implicit def Principal_Is_UserDiscoverable(p: String) = new {
def findUser(implicit repo: UserRepository) = repo.findUser(p)
}
Then you can do "oxbow".findUser
Thanks to Oxbow's answer, I now have it working, this is only for reference.
First of all, a value that should be passed as an implicit must itself be marked implicit:
class TwoFactorAuthProviderImpl(implicit userRepository: UserRepository) ...
Second, implicit conversions are nice and all, but a method implementation signature must still match the signature of its declaration. So this does not compile, even though there is a conversion from Any to User:
def requiresTwoFactorAuth(principal: User): Boolean = { ... }
But leaving the parameter as Any, as in the declaration, and then using it as a user works just fine:
def requiresTwoFactorAuth(principal: Any): Boolean = {
principal.getSettings().getPhoneUsedForTwoFactorAuthentication() != null
}
Also, the conversion really doesn't have to be in the companion object in this case, so in the end, I left the implicit parameters out.
The full source code:
class TwoFactorAuthProviderImpl(userRepository: UserRepository)
extends TwoFactorAuthProvider {
private implicit def toUser(principal: Any): User = {
val email = principal.asInstanceOf[String]
userRepository.findByEmail(email)
}
def requiresTwoFactorAuth(principal: Any): Boolean = {
//using principal as a User
principal.getSettings().getPhoneUsedForTwoFactorAuthentication() != null
}
...
}

Scala: How can I implement a clone method on a superclass, and use it in a subclass?

I might be approaching this the wrong way, but I'd like to have an object like this:
class MyDataStructure {
def myClone = {
val clone = new MyDataStructure
// do stuff to make clone the same as this
...
clone
}
}
class MyDataStructureExtended(val foo: String) extends MyDataStructure
Then:
val data = MyDataStructureExtended
val dataClone = data.clone
println(dataClone.foo)
So, the problem is that dataClone is of type MyDataStructure, not MyDataStructureExtended as I'd hoped.
I thought about adding a type T to the super class, that the subclass can specify (e.g. itself), but that didn't seem very promising.
As you have suggested, abstract types, or generic parameters, are what you need. Do you require that MyDataStructure not be a trait or abstract class? The following defines MyDataStructure to be an abstract class, but you can make it a trait as well.
abstract class MyDataStructure {
type T
def myClone: T
}
class MyDataStructureExtended(foo: String) extends MyDataStructure {
type T = MyDataStructureExtended
def myClone = new MyDataStructureExtended(foo)
}
The results from the Scala interpreter show that the myClone method defined in MyDataStructureExtended is the correct type.
scala> val mde = new MyDataStructureExtended("foo")
val mde = new MyDataStructureExtended("foo")
mde: MyDataStructureExtended = MyDataStructureExtended#3ff5d699
scala> val cloned = mde.myClone
val cloned = mde.myClone
cloned: MyDataStructureExtended = MyDataStructureExtended#2e1ed620
You might want to restrict T so that its type can only be that of MyDataStructure subclasses
abstract class MyDataStructure {
type T <: MyDataStructure
def myClone: T
}
I don't know your requirements, but I believe that Scala 2.8 will have some nice functionality with case classes and named arguments that allow one to clone case classes with a copy method.
Assuming you want to minimize amount of ceremony in the subclasses, here is my suggestion:
class A extends Cloneable {
protected[this] def myCloneImpl[T] = {
val justLikeMe = this.clone
// copy values and such.
// Note that the Object.clone method already made a shallow copy, but you may want
// to deepen the copy or do other operations.
justLikeMe.asInstanceOf[T]
}
def myClone = myCloneImpl[A]
}
class B extends A {
override def myClone = myCloneImpl[B]
}
By extending java.lang.Cloneable and calling the Object.clone method, you ensure that your runtime type is the same as the object being cloned. The static type is coerced with a type-cast (asInstanceOf[T]). You will need to override the myClone method in each subclass and specify the type, but it should be a one-liner.
Hard to say whether you're doing it right with such a vague problem description, but it's actually pretty straightforward to do this. You can simply override myclone in MyDataStructureExtended such that it returns the more specific type. When you have a variable of the more specific type, you'll be able to use the more specific clone method as well.
Example code in case that description was unclear:
class A {
def getMe = this
}
class B extends A {
override def getMe = this
def isAnInstanceOfB = true
}
And a corresponding REPL session:
scala> val a = new A
a: A = A#1a6eeab
scala> val b = new B
b: B = B#a36771
scala> a.getMe
res0: A = A#1a6eeab
scala> a.getMe.isAnInstanceOfB
<console>:7: error: value isAnInstanceOfB is not a member of A
a.getMe.isAnInstanceOfB
^
scala> b.isAnInstanceOfB
res2: Boolean = true
scala> b.getMe.isAnInstanceOfB
res3: Boolean = true
I think this could be the solution. This is not inherited and you can do some modification to achieve your thing. Good Luck.
class CloneableClass extends scala.Cloneable {
def myMethod: Unit = println("Inside "+this.getClass)
override def clone(): CloneableClass =super.clone().asInstanceOf[this.type]
}
class CloneableDemo {
val cc = new CloneableClass
val cc1 = cc.clone()
cc1.myMethod
}
object CloneObject extends App {
val cd = new CloneableDemo
}

Method polymorphism

I am trying to write a generic method f[T](id:String) that is something like this:
case class A(x:String)
case class B(y:String)
case class C(z:String)
def f[T](id:String): T = { /* equivalent to T(id) */ }
val result1:A = f[A]("123") // returns A("123")
val result2:B = f{B]("345") // returns B("345")
val result3:C = f[C]("567") // returns C("567")
Unfortunately I cannot figure out how to work with the type T inside the method, besides using reflection. By "working with the type T" i mean for example being able to do something like the following, which I know doesn't work (for illustration purposes only):
T match {
case A => A(id)
case B => B(id)
}
or simply invoke T(ID) to create a new object of whatever type T is.
I can of course break up this into three methods:
def f1(id:String): A = { A(id) }
def f2(id:String): B = { B(id) }
def f3(id:String): C = { C(id) }
val result1:A = f1("123") // returns A("123")
val result2:B = f2("345") // returns B("345")
val result3:C = f3("567") // returns C("567")
but I'm hoping there is a way to keep it as one generic method to avoid some ugly boilerplate code duplication, and still be nearl as fast as the tree method version.
If you do not want to use reflection (ClassTag or TypeTag), you could use a Factory type class to achieve the desired functionality (unless it defeats the purpose of your generic function by generating a lot of duplicated simple code ;)).
case class A(s: String)
case class B(s: String)
case class C(s: String)
trait Factory[T] extends ((String) => T) {
def apply(arg: String): T
}
object Factory {
implicit object AFactory extends Factory[A] {
override def apply(arg: String): A = A(arg)
}
implicit object BFactory extends Factory[B] {
override def apply(arg: String): B = B(arg)
}
implicit object CFactory extends Factory[C] {
override def apply(arg: String): C = C(arg)
}
}
def create[T : Factory](arg: String): T = implicitly[Factory[T]].apply(arg)
create[A]("foo") | -> res0: A = A(foo)