class can't have main() in scala? - scala

I'm a beginner of Scala.
In Calulator.scala file
class Calulator {
var brand: String ="HP"
def add(m:Int, n:Int):Int = m+n
}
In CalculatorTest.scala file
object CalulatorTest {
def main(args:Array[String]) {
val cal = new Calulator
println(cal.add(1,2))
}
}
Compile two scala files and run CalculatorTest. This works.
My question is can I make them as one scala file like Java?
In Calulator.scala file
class Calulator {
var brand: String ="HP"
def add(m:Int, n:Int):Int = m+n
def main(args:Array[String]) {
val cal = new Calulator
println(cal.add(1,2))
}
}
This doesn't work !!!
I googled it and looks like main() should be in object.
Is there a way to put them in one file to run main()?

To put them in one file use the concept of the 'Companion Object'.
The class and companion object must be in the same file and share the same name.
class Calculator {
var brand: String = "HP"
def add(m: Int, n: Int): Int = m + n
}
object Calculator {
def main(args:Array[String]) {
val cal = new Calculator
println(cal.add(1,2))
}
}
Further reading: http://docs.scala-lang.org/tutorials/tour/singleton-objects.html

The simple answer is No
a deeper answer is that the scala compiler refers to an object as static and class it refers as regular.
when you want to run Java program your main must be declared as static otherwise the JVM will not recognize it as your program entry point.
regards the question about is it possible to union both of them ,the answer is not because thats how the scala compiler works.
The compiler would create MyClass$.class for scala object and MyClass.class for scala class thats why you should never ever call your class something like :
class MyClass$ {
}
because it will override the companion object for MyClass.

Related

Type class pattern: simulacrum boosted method not found

I have a requirement to be able to count number of times AtomicReference[V].get is called in a class that has as field an array of wildcarded atomic references.
To that end, first, I've extended java's AtomicReference[V]:
import java.util.concurrent.atomic.{AtomicInteger => AInt, AtomicReference => ARef}
class MyAtomicReference[V] extends ARef[V]{
private val getCounter: AInt = new AInt(0)
def getAndListen(): V = {
getCounter.getAndIncrement()
super.get()
}
def counter(): Int = getCounter.get()
def resetCounter(): Unit = getCounter.set(0)
}
Then I've added trait AtomicRefCounter which declares the method that I would wish to invoke:
import simulacrum.typeclass
#typeclass trait AtomicRefCounter [R[_], T] {
def countGets(container: R[T]): Int
}
Lastly, I've defined a default AtomicArrayRefCounter in the object DefaultAtomicRefCounters:
object DefaultAtomicRefCounters {
implicit val arrayOfAtomicsTraverser = new AtomicRefCounter[Array, MyAtomicReference[_]] {
override def countGets(container: Array[MyAtomicReference[_]]): Int = container map(_.counter()) sum
}
}
Despite that when I try to call the traverseAtomics() on a corresponding array in a test, I do not see it (I am using Intellij IDEA):
behavior of "removeO1"
"method" should "remove an element from the pool with time O(1)" in new IntPoolBuilder {
import org.learningconcurrency.traditional_concurrency.helpers.DefaultAtomicRefCounters._
pool.buckets.countGet
}
A piece of advice on what I am missing would really help. Usage of simulacrum is not mandatory - if you feel you know how to solve this without it, I would love to hear that.
update:
This is how the buckets are implemented:
class Pool[T] {
type TimeStampedList = (List[T], Long)
val parallelism: Int = Runtime.getRuntime.availableProcessors * 32
val buckets = new Array[MyAtomicReference[TimeStampedList]](parallelism)
...
I think, you might have gotten wrong how implicits work.
If I read everything correctly, then in your code
implicitly[AtomicRefCounter[Array, MyAtomicReference[_]]].countGets(pool.buckets)
should work.
I you wanted to call countGets on the Array you should use the EnrichMyLibrary pattern.
object DefaultAtomicRefCounters {
implicit class RichArray(private underlying: Array[MyAtomicReference[_]] extends AnyVal {
def countGets: Int = underlying.map(_.counter()).sum
}
}
As disappointing as it is, I couldn't make it work with simulacrum annotation, so I've followed Sascha's advise. I just modified slightly his second example (I couldn't get it to work with implictly) so it compiles and works:
object TraditionalConcurrencyHelpers {
implicit class CountArrayAtomicGetsOps(wrapper: Array[MyAtomicReference[(List[Int], Long)]]) {
def countGets()(implicit atomicRefCounter: AtomicRefCounter[Array, MyAtomicReference[(List[Int], Long)]]): Int = atomicRefCounter.countGets(wrapper)
}
}
With this I have no problem calling countGets on the array:
behavior of "removeO1"
"method" should "remove an element from the pool with time O(1)" in new IntPoolBuilder {
import TraditionalConcurrencyHelpers._
import org.learningconcurrency.traditional_concurrency.helpers.DefaultAtomicRefCounters._
//call pool.removeO1 (not implemented yet)
pool.buckets.countGets() shouldEqual 1
}

Invoking scala classes which extends traits during runtime

I am relatively new to scala so please bear me if I asked silly questions.
I have a requirement where I need to invoke a method run time.
I have a trait which is being extended by two classes
trait Animal {
def walk():DataFrame
}
This is extended by two classes.
class Dog(sparkSession: SparkSession) extends Animal {
def walk():DataFrame = {
.............
}
}
class Cat(sparkSession: SparkSession) extends Animal {
def walk():DataFrame = {
.............
}
}
Now from a config file I will get a list of these class names
Lets say like this
val animals = ["com.xy.Dog","com.xy.Cat"]
I need to invoke these classes and execute walk methods.
Can I do something like this?
animals.forEach{ animalString =>
val animalObject = Class.forName(animalString ).newInstance().asInstanceOf(Animal)
animalObject.walk
}
There are a few issues, let's take them one by one:
To build a list in scala you need to do:
val animals = List("com.xy.Dog", "com.xy.Cat")
The forEach method is actually foreach, so there's a small typo. Finally, when you call the newInstance you should get the appropriate constructor before that, otherwise it will use the default one.
animals.foreach { animalString =>
val animalObject = Class.forName(animalString)
.getConstructor(classOf[DataFrame]) // Get the constructor for a DataFrame argument
.newInstance(dataframe) // Pass the dataframe instance
.asInstanceOf[Animal]
animalObject.walk
}
I've made a couple of small changes to the code for you to see it working. You can run the app to see the output:
class Dog extends Animal {
def walk(): Unit = { println("I'm a dog.") }
}
class Cat extends Animal {
def walk(): Unit = { println("I'm a cat.") }
}
object AnimalTest extends App {
val animals = List("com.xy.Dog", "com.xy.Cat")
animals.foreach { animalString =>
val animalObject = Class.forName(animalString)
.newInstance()
.asInstanceOf[Animal]
animalObject.walk
}
}
Note that I've removed the constructor arguments here to easily build instances. The rest is about the same. I hope this helps you.

How to call an overriden method using reflection?

Consider we have the following:
class Base { def name = "Base" }
class Successor extends Base {
override def name = "Successor"
}
I have tried to do the following (took from How to call a superclass method using Java reflection):
import java.lang.invoke.{MethodHandles, MethodHandle, MethodType}
object TestApp {
def main(args: Array[String]) {
val a = new Successor;
val h1 = MethodHandles.lookup().findSpecial(classOf[Base],
"name",
MethodType.methodType(classOf[String]),
classOf[Successor]);
println(h1.invoke(a));
}
}
but I get a runtime exception:
java.lang.IllegalAccessException: no private access for invokespecial: class Successor, from TestApp$
I was told that it is possible that Java reflection may not work correctly for Scala. Is it true? Or I simply do something wrong?
Actually, you can NOT even do it in Java. Note, in the answer of "How to call a superclass method using Java reflection", it works because the Test extends the Base: public class Test extends Base {...}.
It looks like it is possible and Java reflection works for Scala as well, I just didn't read all answers for How to call a superclass method using Java reflection.
The following code works:
object TestApp {
def main(args: Array[String]) {
val a = new Successor;
val impl_lookup = classOf[MethodHandles.Lookup].getDeclaredField("IMPL_LOOKUP")
impl_lookup.setAccessible(true)
val lkp = impl_lookup.get(null).asInstanceOf[MethodHandles.Lookup];
val h1 = lkp.findSpecial(classOf[Base],
"name",
MethodType.methodType(classOf[String]),
classOf[Successor])
println(h1.invoke(a)) // prints "Base"
println(a.name) // prints "Successor"
}
}
Thanks to Jesse Glick for this solution.

Scala - construction order and early definition syntax

I'm trying to learn Scala and thought I would begin by reading "Scala for the Impatient". There he cites the problem of construction order by using the following classes:
class Animal {
val range: Int = 10
val env: Array[Int] = new Array[Int](range)
}
class Ant extends Animal {
override val range: Int = 2
}
and then he explained why the env ends up being an empty Array[Int] and proceeds to explain ways to prevent that, including the early definition syntax.
But... can't I prevent that just by doing this:
class Animal(val range: Int = 10) {
val env: Array[Int] = new Array[Int](range)
/* do animal stuff */
}
class Ant(override val range: Int = 2) extends Animal(range) {
/* do ant stuff */
}
??? Why is the early definition syntax really necessary?
I think a better way to look at the need for early instantiation comes from mixing in traits. With traits, you won't have a constructor that you can tweak to get around this kind of issue. Consider this very trivial and completely unrealistic example:
trait Foo{
val bar:String
val barLength = bar.length()
}
object MyFoo extends Foo{
val bar = "test"
}
As it stands right now, this code will throw a NullPointerException when MyFoo is created because bar will not yet be defined when bar.length() is invoked. But if you used early initialization, and redefined MyFoo as:
object MyFoo extends {val bar = "test"} with Foo{
}
then everything works just fine.

What is this Scala 'new' syntax

From the ScalaTest docs:
class ExampleSpec extends FlatSpec {
def fixture =
new {
val builder = new StringBuilder("ScalaTest is ")
val buffer = new ListBuffer[String]
}
...
I don't understand how the new keyword is being used here. fixture is obviously a function, which declares and returns... what? It seems to be an object, since it has members (builder & buffer) that can be accessed with . notation.
Is what is being created here an anonymous class that is a subclass of AnyRef?
Yep, it returns instance of anynomous class. It is not hard to check it by yourself in REPL session:
scala> def fixture = new { val string = "mr. String" }
fixture: Object{val string: String}
Java can do the essentially same thing, believe it or not. The following is valid Java
(new Object() {
public void sayHello() {
System.out.println("hello!");
}
}).sayHello();
The Java version is just a mildly more verbose syntax and has a type system limitation that makes it mostly useless.
More about it here http://james-iry.blogspot.com/2009/04/java-has-type-inference-and-refinement.html