Scala Arraylist with another class - scala

Hi guys i'm a beginner and i have a problem with this code is. I am trying to create an arraylist but it can only use the default class Members
The problem lies in here var memberList : ArrayList[Members] with an error message of :
Error:(13, 30) not found: type Members
var memberList : ArrayList[Members]
Does anyone know a workaround with it?
The sample code is below.
import java.util.{ArrayList}
abstract class Groups(){
val groupName: String
val groupType: String
var memberList : ArrayList[Members]
def addMember(enter: String): Unit = {
memberList.add(enter)
}
def deleteMember(del: String): Any = {
memberList.remove(del)
}
}
class Members(var name: String, var permission: String){
}

Related

Scala Internal Class Typing - Type Mismatch Error

I am experiencing a very strange typing error when running the below code.
The goal of this code is to have a class that can combine other instances of this class with itself, producing the updated instance. (Perhaps I should prefer immutability and return copies, but that's another discussion).
IntelliJ does not complain until I attempt to run the code, then it crashes with
type mismatch found: mic.MyInternalClass
required: MyClass.this.MyInternalClass this.myVar =
this.myVar.combine(mic.myVar)"
IntelliJ Error Message
class MyClass(s: String) {
var myVar: MyInternalClass = new MyInternalClass(s)
def combine(mic: MyClass): MyClass = {
this.myVar = this.myVar.combine(mic.myVar)
this
}
class MyInternalClass(s: String) {
var myInternalVar: String = s
def combine(mic: MyInternalClass): MyInternalClass = {
this.myInternalVar += mic.myInternalVar
this
}
}
}
object App {
def main(args : Array[String]) {
var mc1: MyClass = new MyClass("dog")
var mc2: MyClass = new MyClass("cat")
mc1.combine(mc2)
println(mc1.myVar.myInternalVar)
println(mc2.myVar.myInternalVar)
}
}
Each instance's MyInternalClass is considered a separate type in Scala, so you can't mix this's and mic's MyInternalClass. If that's not what you want, instead of using MyClass#MyInternalClass everywhere it's better to move MyInternalClass declaration to the companion object:
// otherwise you'll need to write MyClass.MyInternalClass explicitly even inside MyClass
import MyClass.MyInternalClass
class MyClass(s: String) {
var myVar: MyInternalClass = new MyInternalClass(s)
def combine(mic: MyClass): MyClass = {
this.myVar = this.myVar.combine(mic.myVar)
this
}
}
object MyClass {
class MyInternalClass(s: String) {
var myInternalVar: String = s
def combine(mic: MyInternalClass): MyInternalClass = {
this.myInternalVar += mic.myInternalVar
this
}
}
}
I just found this link: Referring to the type of an inner class in Scala
It looks like the inner class method needs a special type like so:
def combine(mic: MyClass#MyInternalClass): MyInternalClass = {
Still learning the nuances of why this is the case.

accessing constructor variable in companion object

Getting a compile time error for the following classes in the same file
class FancyGreeting (greeting: String) {
//private var greeting: String=_;
def greet() = {
println( "greeting in class" + greeting)
}
}
object FancyGreeting {
def privateGreeting(f:FancyGreeting) : String = {
f.greeting;
}
}
error: value greeting is not a member of this.FancyGreeting
f.greeting;
The same works if i use the private variable greeting instead of the constructor
You need to denote the constructor parameter as a variable, like so:
class FancyGreeting (val greeting: String) {
//private var greeting: String=_;
def greet() = {
println( "greeting in class" + greeting)
}
}
object FancyGreeting {
def privateGreeting(f:FancyGreeting) : String = {
f.greeting;
}
}
You should write class FancyGreeting(private var greeting: String) { if you want to have the same behavior as when you use the line you commented out. The way you write it (i.e. class FancyGreeting(greeting: String) {) is only giving greeting as a parameter to the constructor, without making it a property.
This said, you should not use ";" to end the lines in Scala. Moreover, it is usually better to use val than var, if you can.
NOTE: this answer might be interesting for you.

Scala case classes with new firebase-server-sdk

Does the new server SDK for firebase firebase-server-sdk (3.0.1) support Scala case class deserialization? The previous firebase java sdk used jackson which you could bolt in a scala module to support case classes. It's unclear if its possible to do something similar with the new SDK? Does it use Gson or some custom class mapper?
In the simplest example:
case class Person(firstName: String, lastName: String, age: Int)
With a Firebase listener setup such as:
var options = new FirebaseOptions.Builder()
.setDatabaseUrl("https://<your firebase>.firebaseio.com")
.setServiceAccount(new FileInputStream("firebase-auth.json"))
.build()
FirebaseApp.initializeApp(options);
var ref = FirebaseDatabase.getInstance().getReference("somepath")
ref.addListenerForSingleValueEvent(new ValueEventListener {
override def onDataChange(dataSnapshot: DataSnapshot): Unit = {
println(dataSnapshot.getValue(classOf[Person]))
}
override def onCancelled(databaseError: DatabaseError): Unit = {
println(databaseError.getMessage)
}
})
This will fail on the getValue call dataSnapshot.getValue(classOf[Person]) with the exception:
Exception in thread "FirebaseDatabaseEventTarget" com.google.firebase.database.DatabaseException: No properties to serialize found on class Person
at com.google.firebase.database.utilities.encoding.CustomClassMapper$BeanMapper.<init>(CustomClassMapper.java:495)
at com.google.firebase.database.utilities.encoding.CustomClassMapper.loadOrCreateBeanMapperForClass(CustomClassMapper.java:285)
at com.google.firebase.database.utilities.encoding.CustomClassMapper.convertBean(CustomClassMapper.java:379)
at com.google.firebase.database.utilities.encoding.CustomClassMapper.deserializeToClass(CustomClassMapper.java:187)
at com.google.firebase.database.utilities.encoding.CustomClassMapper.convertToCustomClass(CustomClassMapper.java:61)
at com.google.firebase.database.DataSnapshot.getValue(DataSnapshot.java:181)
at PetEventsNodeActorSpec$$anonfun$2$$anonfun$apply$mcV$sp$2$$anonfun$apply$mcV$sp$3$$anon$1.onDataChange(PetEventsNodeActorSpec.scala:290)
at com.google.firebase.database.Query$1.onDataChange(Query.java:147)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:57)
at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:45)
at com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:35)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
I've tried adding annotations to the class such as #BeanProperty but then get:
Exception in thread "FirebaseDatabaseEventTarget" com.google.firebase.database.DatabaseException: Class Person is missing a constructor with no arguments
Rather than go down the rabbit hole of annotating or adding code to every case class, any ideas on getting scala case classes to play nicely with the new firebase sdk?
AFAIK, there isn't a way to use a case class directly. I ended up creating plain classes with #BeanProperty annotations and then converting them to case classes. The reason for
Exception in thread "FirebaseDatabaseEventTarget" com.google.firebase.database.DatabaseException: Class Person is missing a constructor with no arguments
is because your class constructor must be nullary (i.e. it cannot take any arguments):
import scala.beans.BeanProperty
case class Person(firstName: String, lastName: String, age: Int) {
def toBean: PersonBean = {
val person = new PersonBean()
person.firstName = firstName
person.lastName = lastName
person.age = age
person
}
}
class PersonBean() {
#BeanProperty var firstName: String = ""
#BeanProperty var lastName: String = ""
#BeanProperty var age: Int = 0
def toCase: Person = Person(firstName, lastName, age)
}
var ref = FirebaseDatabase.getInstance().getReference("somepath")
ref.addListenerForSingleValueEvent(new ValueEventListener {
override def onDataChange(dataSnapshot: DataSnapshot): Unit = {
val record = dataSnapshot.getValue(classOf[PersonBean])
val person = if (record != null) record.toCase else null
}
override def onCancelled(databaseError: DatabaseError): Unit = {
println(databaseError.getMessage)
}
})

Import Class: error: not found: object Controller

I'm a beginner in scala, without java background. I don't understand the import system.
I have my application, where i use the import
import Array._
import List._
import Controller.api
object scalaStart{
def main(args: Array[String]){
var apiCtrl = new api()
apiCtrl.getById(1)
println(apiCtrl.title)
}
}
And this is the class:
package Controller
class api {
var id:Int
var title:String
var description:String
def getById(id:Int){
if(id = 1){
this.id = 1
this.title = s"Title Nummer ${this.id}"
this.description = s"Description Nummer ${this.id}"
}else{
this.id = 1
this.title = s"Artikel mit der ID: ${this.id} existiert nicht."
this.description = s"Kein Eintrag mit der ID: ${this.id}"
}
}
}
i checked also only import api and import controller and wildcards controller._ controller.api._.
Philipp, your code actually does not compile.
In the line if(id=1){ it should be if(id==1).
Try to correct this and rebuild your project.
You will notice that compiler will give you another error:
Error:(5, 7) class api needs to be abstract, since: it has 3
unimplemented members. /** As seen from class api, the missing
signatures are as follows. * For convenience, these are usable as
stub implementations. */ def description_=(x$1: String): Unit = ???
def id_=(x$1: Int): Unit = ??? def title_=(x$1: String): Unit = ???
class api {
^
This is because in Scala you can't leave variable declarations abstract as you could do in Java. Instead of var id:Int you need to put something liek var id:Int = 0 and the same for other declared variables.

Class A cannot be cast to Class A after dynamic loading

Let's say I have:
object GLOBAL_OBJECT{
var str = ""
}
class A(_str: String){
GLOBAL_OBJECT.str = _str
}
and I would like to create 2 copies of GLOBAL_OBJECT (for tests), so I am using different classloader to create obj2:
val obj1 = new A("1")
val class_loader = new CustomClassLoader()
val clazz = class_loader.loadClass("my.packagename.A")
val obj2 = clazz.getDeclaredConstructor(classOf[String]).newInstance("2")
println("obj1.getSecret() == " + obj1.getSecret()) // Expected: 1
println("obj2.getSecret() == " + obj2.asInstanceOf[A].getSecret()) // Expected: 2
which results following error:
my.packagename.A cannot be cast to my.packagename.A.
IntelliJ Idea seems to do it correctly, I can run obj2.asInstanceOf[A].getSecret() in "expression" window during debug process without errors.
PS. I have seen similar questions, but I could not find any not regarding loading class from .jarfile.
You're not going to be able to get around Java's class casting, which requires strict typing, within the same ClassLoader. Same with traits/interfaces.
However, Scala comes to the rescue with structural typing (a.k.a. Duck Typing, as in "it quacks like a duck.") Instead of casting it to type A, cast it such that it has the method you want.
Here's an example of a function which uses structural typing:
def printSecret(name : String, secretive : { def getSecret : String } ) {
println(name+".getSecret = "+secretive.getSecret)
}
And here's sample usage:
printSecret("obj1", obj1) // Expected: 1
printSecret("obj2", obj2.asInstanceOf[ {def getSecret : String} ]) // Expected: 2
You could, of course, just call
println("secret: "+ obj2.asInstanceOf[ {def getSecret : String} ].getSecret
Here's full sample code that I wrote and tested.
Main code:
object TestBootstrap {
def createClassLoader() = new URLClassLoader(Array(new URL("file:///tmp/theTestCode.jar")))
}
trait TestRunner {
def runTest()
}
object RunTest extends App {
val testRunner = TestBootstrap.createClassLoader()
.loadClass("my.sample.TestCodeNotInMainClassLoader")
.newInstance()
.asInstanceOf[TestRunner]
testRunner.runTest()
}
In the separate JAR file:
object GLOBAL_OBJECT {
var str = ""
}
class A(_str: String) {
println("A classloader: "+getClass.getClassLoader)
println("GLOBAL classloader: "+GLOBAL_OBJECT.getClass.getClassLoader)
GLOBAL_OBJECT.str = _str
def getSecret : String = GLOBAL_OBJECT.str
}
class TestCodeNotInMainClassLoader extends TestRunner {
def runTest() {
println("Classloader for runTest: " + this.getClass.getClassLoader)
val obj1 = new A("1")
val classLoader1 = TestBootstrap.createClassLoader()
val clazz = classLoader1.loadClass("com.vocalabs.A")
val obj2 = clazz.getDeclaredConstructor(classOf[String]).newInstance("2")
def printSecret(name : String, secretive : { def getSecret : String } ) {
println(name+".getSecret = "+secretive.getSecret)
}
printSecret("obj1", obj1) // Expected: 1
printSecret("obj2", obj2.asInstanceOf[ {def getSecret : String} ]) // Expected: 2
}
}
Structural typing can be used for more than one method, the methods are separated with semicolons. So essentially you create an interface for A with all the methods you intend to test. For example:
type UnderTest = { def getSecret : String ; def myOtherMethod() : Unit }
One workaround to actually run some method from dynamically delivered object instead of casting it is to use reflection in order to extract particular method, from new class and then invoke it on our new object instance:
val m2: Method = obj2.getClass.getMethod("getSecret")
m2.invoke(obj2)
The class file that contains obj2.asInstanceOf[A].getSecret() should be reloaded by CustomClassLoader, too.
And you must not use any class that references to A unless you reload the class by the same class loader that reloads A.