Importing object without class - scala

I'm trying to import an object from another .scala file that doesn't exist inside a class. I've found you can import a class like in here Scala, importing class. Is there a way to import an object without having a class around it?
Thanks

Importing a class and importing an object work the same in scala.
If you have a class
package com.package1
class MyClass{}
and an object
package com.package2
object MyObject{}
You import both the exact same way
package com.package3
import com.package1.MyClass
import com.package2.MyObject
import syntax is the same no matter what you are importing, whether it's an object, a class, a trait, a method, or a field

Yes, Scala can do exactly what you ask, and this is used frequently. Here is an example:
object Blah {
val x = 1
val y = "hello"
}
object Main extends App {
import Blah._
println(s"x=$x; y=$y")
}
Output is:
x=1; y=hello
You can also import members of a class instance, which blew my mind the first time I saw it.

If you are talking about companion objects, they are not defined inside a class, but after the class definition:
class AClass {
def sayHello() = {
println(AClass.Hello)
}
}
object AClass {
private val Hello = "hello"
}
You should have no problem importing it.

Related

loading external scala scripts into a scala file

i originally made scripts with many functions on 2 individual scala worksheets. i got them working and now want to tie these individual scripts together by importing and using them into a third file. from what i have read you can not simply import external scripts you must first make them into a class and put them into a package. so i tried that but i still couldn't import it
i know this may be a bit basic for this site but im struggling to find much scala documentation.
i think my problem might span from a missunderstanding of how packages work. the picture below might help.
my program example
adder.scala
package adder
class adder {
def add_to_this(AA:Int):Int={
var BB = AA + 1;
return BB
}
}
build.scala
package builder
class build {
def make_numbers(){
var a = 0;
var b = 0;}
}
main.sc
import adder
import builder
object main {
adder.adder.add_to_this(10);
}
the errors i get are
object is not a member of package adder
object is not a member of package builder
Classes in scala slightly differ from classes in java. If you need something like singleton, you'll want to use object instead of class i.e.:
package com.example
object Main extends App {
object Hide{
object Adder{
def addToThis(AA:Int):Int = AA + 1
}
}
object Example{
import com.example.Main.Hide.Adder
def run(): Unit = println(Adder.addToThis(10))
}
Example.run()
}
Consider objects like packages/modules which are also regular values. You can import an object by its full path, i.e. com.example.Main.Hide.Adder you can also import contents of an object by adding .{addToThis}, or import anything from object by adding ._ after an object.
Note that classes, traits and case classes could not be used as objects, you can't do anything with it unless you have an instance - there are no static modifier.

Initialising variables in a mock class scala

I am writing unit tests for an akka actor model implementation. The system contains classes and traits that need to be initialised. My issue lies with the testing of the methods. When I mock required parameters for a class, it removes the intelij compiler error, however all of the variables are set to null.
I have attempted to use
when(mock.answer).thenReturn(42)
and directly assigning the variables
val mock.answer = 42
The above two through compilation errors. "When" is not recognised and directly assigning values cases a runtime error.
Any insight would be much appreciated.
I am not sure if I understood your issue correctly, but try the self contained code snippet below and let me know if it is not clear enough:
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatest.mockito.MockitoSugar
import org.scalatest.{FunSuite, Matchers}
import org.mockito.Mockito.when
#RunWith(classOf[JUnitRunner])
class MyTest extends FunSuite with Matchers with MockitoSugar {
trait MyMock {
def answer: Int
}
test("my mock") {
val myMock = mock[MyMock]
when(myMock.answer).thenReturn(42)
myMock.answer should be(42)
}
}

Accessing Singleton values in Play for Scala

I have the following singleton defined in Scala
package main
import javax.inject._
#Singleton
class Properties {
val timeout = 120
}
how do I access it from other programs? I tried main.Properties.timeout but it throws a compilation error saying that a companion object was not found
If you want to access it in the way, that you've mentioned: main.Properties.timeout, then use companion object instead:
class Properties {
// ...
}
object Properties {
val timeout = 120
// ...
}
With #Singleton annotation, you have to inject that service somewhere, to be able to use it. So something like this:
import javax.inject._
import main.Properties
class SomeService #Inject() (props:Properties)() {
println(props.timeout)
}
Here is documentation about DI for PlayFramework: https://www.playframework.com/documentation/2.5.x/ScalaDependencyInjection - for the latest one (not 2.0), but it is a good start point.

Guice and Play2 Singleton from trait

I am using Play with Scala and I am trying to create a singleton, and i want to inject it from its trait and not directly.
for example:
#ImplementedBy(classOf[S3RepositoryImpl])
trait S3Repository {
}
#Singleton
class S3RepositoryImpl extends S3Repository {
}
But this fails with error:
trait Singleton is abstract; cannot be instantiated
I have tried several combinations and they all produce the same.
I come from Spring background and its very natural there? am i missing something about how Guice handles this type of Injection?
Thanks.
As pointed out by #Tavian-Barnes, the solution is to ensure you have the following import:
import javax.inject.Singleton
I have here a "complete" working example, just hope that I'm not stating the obvious...
package controllers
import play.api._
import play.api.mvc._
import com.google.inject._
class Application #Inject() (s3: S3Repository) extends Controller {
def index = Action {
println(s3.get)
Ok
}
}
#ImplementedBy(classOf[S3RepositoryImpl])
trait S3Repository {
def get: String
}
#Singleton
class S3RepositoryImpl extends S3Repository {
def get: String = "bla"
}
Whenever you mark a class' constructor with #Inject the Guice will manage the injection of the instance itself. So, if you marked your class as #Singleton, Guice will create and will always give you just that one instance. Nobody can stop you from manually instantiating a class in your code... You can explore it in detail at Play.
Use below import, instead of import javax.inject.Singleton
import com.google.inject.{Inject, Singleton}
Import both Inject and Singleton.
import javax.inject.{Inject, Singleton}
Refrain from using:
import com.google.inject.{Inject, Singleton}
as play framework requires the javax import

Scala importing a file in all files of a package

I need to use an implicit ordering that has been defined in an object in a file
abc
in the following way:
object abc{
implicit def localTimeOrdering: Ordering[LocalDate] = Ordering.fromLessThan(_.isBefore(_))
}
So, I make a package object
xyz
inside a file 'package.scala' that in turn is in the package 'xyz' that has files in which I need the implicit ordering to be applicable. I write something like this:
package object xyz{
import abc._
}
It does not seem to work. If I manually write the implicit definition statement inside the package object, it works perfectly. What is the correct way to import the object (abc) such that all of its objects/classes/definitions can be used in my entire package 'xyz' ?
You cannot import the implicit conversions in that way, you will have to:
Manually write them inside the object:
package obj {
implicit def etc//
}
Or obtain them via inheritance/mixins:
package obj extends SomeClassOrTraitWithImplicits with AnotherTraitWithImplicits {
}
For this reason, you usually define your implicit conversions in traits or class definitions, that way you can do bulk import with a single package object.
The usual pattern is to define a helper trait for each case.
trait SomeClass {
// all the implicits here
}
object SomeClass extends SomeClass {}
Doing this would allow you to:
package object abc extends SomeClass with SomeOtherClass with AThirdClass {
// all implicits are now available in scope.
}