How to invoke class constructor, if class and object is in the same file - scala

In MyFactory.scala, object and Class defined in the same file with same name, like this
package com.mydomain.app.module
object MyFactory{
val a1 = "a1"
val b1 = "b1"
}
class MyFactory(config:Configuration){
//blah....
}
Problem is I cannot Initiate MyFactory object in another class
var myFactory = new Myfactory(defaultConfiguration)
due to the error
not found: type MyFactory
All I did was a common import
import com.mydomain.app.module.MyFactory
What is the valid way to initiate an object of the class, if I can't modify anything from MyFactory.scala (legacy code)

var myFactory = new MyFactory(defaultConfiguration)
is the valid way to initiate an object of the class.
import com.mydomain.app.module.MyFactory should be enough for bringing MyFactory (and its companion) to the scope.
Sometimes "object app is not a member of package com.mydomain" can mean that you're trying to recompile MyFactory.scala referring to something not compiled in com.mydomain...
Try mvn clean compile.

Related

Scala - meaning of "companion contains its own main method, which means no static forwarder can be generated"

Given the following class and its companion object:
class B extends A
object B extends B
Where A is an abstract class in another file:
abstract class A {
def main(args: Array[String]): Unit = println("hey")
}
The above code is packaged into an uber-jar using the sbt assembly plugin, where the entry point is object B main method inherited from class B.
The above works fine. It runs. No problem at all.
Hoewver, sbt keeps warning:
[warn] B has the main method with parameter type Array[String], but B will not be a runnable program.
[warn] Reason: companion contains its own main method, which means no static forwarder can be generated.
[warn] object B extends B
Do you know the meaning of this warning?
And why sbt assurance that object B won't run, doesn't happen?
Thank you.
For a class to be runnable in java, main needs to be static. Yours isn't, so, the object isn't runnable. That's what compiler is telling you.
Just rename main in A to something else, and then add a main in the object, that calls it.
It does not run for me.
I have this file B.scala.
package foo.bar
abstract class A {
def main(args: Array[String]): Unit = println("hey")
}
class B extends A
object B extends B
When I try to run foo.bar.B I get an error:
sbt> runMain foo.bar.B
[info] running foo.bar.B
[error] (run-main-0) java.lang.NoSuchMethodException: foo.bar.B.main is not static
And the reason is exactly as the warning says. Class B contains a non-static main method which it inherited from class A. You can't have 2 methods with exactly the same name and type signature in one class, even if one is static and another in non-static. This means that the compiler cannot generate a static main method in class B that forwards to the non-static main method in object B.
Why it does run correctly for you I don't know.
It's not so hard to avoid this problem. Just don't use the companion object as an entrypoint. I.e. rename either class B or object B.
package foo.bar
abstract class A {
def main(args: Array[String]): Unit = println("hey")
}
class BClass extends A
object B extends BClass

Using Jenkins Shared Libraries as classes

I have a Jenkins file, and i'm trying to instantiate a groovy class from my shared library. I get "unable to resolve class Test "
I have a src/com/org/foo.groovy file in a shared library :
package com.org
class Test implements Serializable{
String val
Test(val) {
this.val = val
}
}
and I'm trying to instantiate it in my jenkinsfile
#Library('Shared-Library#master')
import com.org //also tried to use with .foo with no success
def t = new Test("a") //doesnt work
def t = new foo.Test("a")//doesnt work
def t = new com.org.foo.Test("a")//doesnt work
What does work is if I refer to the file as a class (which I don't have the access to its constructor). That is:
#Library('Shared-Library#master')
def t = new foo.com.org.foo()
This is nice, and lets me use foo functions. However, I lose the power to give the class constants and construct it with parameters.
Any idea how I can define and use a class from shared library?
Thanks
The scope of your class is a default scope. you can change the scope to public
It throwing an error because you have created an object of a class outside the script block. try below code and it should work. Try below code
#Library('Shared-Library#master')
import com.org.*;
stages{
stage('Demo') {
steps{
script{
def t = new Test("a") //this should work
}
}
}
}

Importing object without class

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.

A class imported from a companion not usable as the constructor parameter default value

Consider following code:
object Main extends App {
object Project {
case class Config(rules: Seq[String] = Seq.empty)
}
import Project._
//case class Project(root: String, config: Config) // compiles fine
//case class Project(root: String, config: Project.Config = Project.Config()) // compiles fine
case class Project(root: String, config: Config = Config()) // error: not found: type Config
}
Why does the last version not compile (same with Config = Config.apply())?
It is not clear to me if this is a bug or not, but here is why it produces an error:
Consider this, which works:
import Project._
object Project {
case class Config()
}
case class Project(config: Config = Config())
When you add a default argument the compiler generates a method to calculate the value. When that value is a constructor default, that method is added to the companion object of the class. So the compiler will generate this method:
def <init>$default$1: Project.Config = Config()
Which will get added to your Project object.
The Scala type checker generates an object tree of Contexts. Each context has a reference to the context of it's outer scope. So the generated method gets a context and that generated method's outer scope is the Project companion object.
When the type checker attempts to resolve Config() it traverses all the enclosing contexts and cannot find Config (I am not sure why, and this may be a bug).
Once it has exhausted the contexts it resolves the imports which has the import Project._! The type checker is happy because it can now traverse the imports and find the apply method.
Now when you move the import below Project:
object Project {
case class Config()
}
import Project._
case class Project(config: Config = Config())
In this case the imports available to the generated method does not have the Project._ import (this may also be a bug), I'm assuming because it's below the object definition which is where the generated method lives. The type checker then throws an error because it can't find Config.
What appears to be happening is when the type checker is resolving Config() it needs the import above the Project companion object as it needs to process the import to be able to resolve it and unless the import is above Project that import is not in scope.
For those who wish to debug further take a look at Contexts.lookupSymbol which is where the lookup is happening

Discover if a class has been declared inside a particular module type

I am writing a DSL which describes a structure. The DSL uses Types to reference classes which will later be instantiated. I would like to enforce that a particular Type has been declared within a particular module. This can be a runtime check after the DSL has been compiled.
In essence I need to access the outer element starting from the inner class and check it is of the correct type and get a reference to it.
If I get the child type I can get its symbol using reflection by calling to typeSymbol and in the resulting symbol I see that I can call owner to get the outer type symbol. However if I try to reflect the parent as a Module (even when the parent it is a module) it throws an exception.
Lets put an example:
trait TheMixin
object TheParent extends TheMixin {
case class TheChild()
}
object TestDiscoverParent extends App {
import scala.reflect.runtime.{currentMirror => cm, universe => ru}
val theChildType = ru.typeOf[TheParent.TheChild]
val theChildOwner = theChildType.typeSymbol.owner
println(theChildOwner)
val theParentModuleSymbol = theChildOwner.asModule
val theParentRef = cm.reflectModule(theParentModuleSymbol).instance
println(theParentRef.isInstanceOf[TheMixin])
}
In this example, the line println(theChildOwner) will print
object TheParent
But the call to theChildOwner.asModule throws an exception:
Exception in thread "main" scala.ScalaReflectionException: object TheParent is not a module
How can I get a reference to the outer object wrapper?
There seems to one more indirection, the owner is a "module class". I'm not exactly sure what that means, probably just that technically behind every singleton object there is also a class that is instantiated once.
So the following seems to work:
object TestDiscoverParent extends App {
import scala.reflect.runtime.{currentMirror => cm, universe => ru}
val theChildType = ru.typeOf[TheParent.TheChild]
val theChildOwner = theChildType.typeSymbol.owner
println(theChildOwner)
require(theChildOwner.isModuleClass)
val theParentModuleClass = theChildOwner.asClass
val theParentModuleSymbol = theParentModuleClass.module.asModule
val theParentRef = cm.reflectModule(theParentModuleSymbol).instance
println(theParentRef.isInstanceOf[TheMixin])
}