Per the title, this seems like it should be a standard operation, but googling so far has not yielded any results for me. Suppose I have a java class like the following:
public class Outer {
public static class Inner {
int x;
Inner(int x) {
this.x = x;
}
}
}
Now, suppose I have a scala object like the following:
object Blah {
def main(args: Array[String]) {
val v = new Outer.Inner(4) // doesn't work
}
}
Instead of compiling as expected, I receive a "type Inner is not a member of Outer" error.
Is there a way to make the above code work as expected?
I test your example and seems to be correct.
If you still have problems try this:
object Blah {
import correct_package.Outer.Inner
def main(args: Array[String]) {
val v = new Inner(4)
}
}
Related
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
}
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.
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.
I am doing some basic handson in scala.. i am getting compile-time error at the place of defining a method called processList.
The compile time error is
Multiple markers at this line:
- only classes can have declared but undefined
members
My code is as follows,
package pack1
import scala.io.Source
case class Record(id:Int, name:String, city:String)
object ReadingFile {
def main(args: Array[String]): Unit = {
val fileLoc:String = "/home/edureka/surender/inputfiles/records.txt"
val fileData:List[String] = Source.fromFile(fileLoc).getLines().toList
val fileList =fileData.map { eachLine => {
val Array(a:String,b:String,c:String) = eachLine.split(",")
Record(a.toInt,b,c)
} }
println(fileList)
processList(fileList)
}
def processList(myList:List[Record])
{
}
}
I dont know how to fix this, Can somebody help me on this?
Because of the new line after def processList(myList:List[Record]) Scala compiler thinks that the method implementation is not given and below block {} does not belong to the method. So compiler thinks its a abstract method.
Declare processList like this
def processList(myList:List[Record]) {
}
or
def processList(myList:List[Record]): Unit = {
}
Instead of this
def processList(myList:List[Record])
//remove this line to fix the error
{
}
The problem with this code is here,
def processList(myList:List[Record])
// <------ Notice this blank line
{
}
This leads the compiler to think that these are two different statements. And hence it thinks that you have left def processList(myList:List[Record]) without providing an implementation. And a class or case class and object can not have un-implemented members.
So... just fix that,
def processList(myList:List[Record]): Unit = {
}
In Java I usually do something like:
class Hello {
public Hello() {
System.out.println("hello");
}
public static void main(String args[]) {
new Hello();
}
}
How do I do something similar in Scala? I start off with Hello being a Scala object like so:
object Hello {
// constructor goes here
def main(args: Array[String]): Unit = {
println("hello") // new Hello() would go here
}
}
but I can't instantiate that. If I change I change the object keyword to class then the scala compiler complains i.e.
class Hello {
println("hello")
def main(args: Array[String]): Unit = {
new Hello()
}
}
I know I'm probably on completely the wrong track here but I'd like to be put out of my misery.
Usually for this in Scala i use objects representing the application:
object Hello extends App {
println("hello")
}
I don't think you understand what a Scala object is. It is actually the equivalent of a Java singleton, where an anonymous class is created and instantiated in place.
If you would recompile the code to Java in this scenario:
object Hello {}
It would get something like:
public class Hello$ {
public static Hello$ $MODULE = new Hello$()
}
This is already a singleton, an equivalent of a val. You can even do:
val x = Hello; // x will be of type Hello.type